B. Binary Vector (逆元 / 数学 / 前缀和) 2020牛客暑期多校训练营(第六场)

传送门

在这里插入图片描述
在这里插入图片描述
思路:

  • 推算出相应的f(i),答案就是前n个f(i)依次进行亦或,而在亦或前需要将f(i)的P/Q形式转换成P*(Q^-1) 形式,而Q^-1即为Q的逆元。
  • 推算公式:f(i) = f(i-1) * (2^i - 1) / 2^i。
    整理可得分母Q就是(2 ^ i) * i!,而分子P为(2^1 - 1)(2^2 - 1)……*(2^i - 1)。
  • 然后我们可用两个数组分别计算f(i)的分子和分母,且我们不必每次都再求一次逆元,只需要对于分母的基数2的逆元,后面再累乘即可。
  • 而关于线性独立的具体分析可见题解

代码实现:

#include<bits/stdc++.h>
//#define endl '\n'
#define null NULL
#define ll long long
#define int long long
#define pii pair<int, int>
#define lowbit(x) (x &(-x))
#define ls(x) x<<1
#define rs(x) (x<<1+1)
#define me(ar) memset(ar, 0, sizeof ar)
#define mem(ar,num) memset(ar, num, sizeof ar)
#define rp(i, n) for(int i = 0, i < n; i ++)
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define pre(i, n, a) for(int i = n; i >= a; i --)
#define IOS ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int way[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
using namespace std;
const int  inf = 0x7fffffff;
const double PI = acos(-1.0);
const double eps = 1e-6;
const ll   mod = 1e9 + 7;
const int  N = 2e7 + 5;

//B的公式应该是f(n)=f(n-1)*(2n-1)/2n
//1/2的逆元=1*quick_pow(2,mod-2)
int t, n, maxx, a[N];

inline void read(long long &x){
    char t=getchar();
    while(!isdigit(t)) t=getchar();
    for(x=t^48,t=getchar();isdigit(t);t=getchar()) x=x*10+(t^48);
}
void Inint(){
    a[1] = 500000004; //a[1]正好表示 1/2 的逆元
    int inv = a[1], Q = 2, P = 1;
    for(int i = 2; i < N; i ++){
        inv = inv * a[1] % mod; //inv表示f(i)的Q^-1的逆元
        Q = (Q*2) % mod;
        P = a[i-1] * (Q-1+mod) % mod;
        a[i]= P * inv % mod;
//        a[i] = (a[i]+mod) % mod;
    }
    for(int i = 2; i <= N; i ++) a[i] ^= a[i-1];
}
signed main()
{
    Inint();
    read(t);
    while(t --){
        read(n);
        printf("%lld\n", a[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Satur9/article/details/107624702
今日推荐