思路:
- 推算出相应的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;
}