\(f_n\)的意思是随机生成 n 个 n 维向量,这 n 个向量线性无关的概率。
线性无关指的是向量之间不能相互表示,既不存在解(至少要有一个 k 非0)使得\(k_1\vec{a_1}+...+k_n\vec{a_n}=0\)这个式子成立。
依次选取n个向量:
第一个向量非零即可,有\(2^n-2^0\)种
第二个要求非零且不能被第一个所表示,有\(2^n-2^1\)种
第三个要求非零且不能被第一个和第二个表示,有\(2^n-2^2\)种
……
第n个要求非零且不能被上面的向量表示,有\(2^n-2^{n-1}\)种
得到通项公式为\(f_N=\frac{\prod_{i=0}^{N-1}(2^N-2^i)}{2^{N^2}}\)
但是N太大了,所以求出递推公式\(f_N=\frac{2^N-1}{2^N}f_{N-1}\)
// Created by CAD
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e7+1;
const int mod=1e9+7;
ll f[maxn];
int qpow(int x,int n){
ll ans=1;
while(n>0){
if(n&1) ans=ans*x%mod;
n>>=1,x=1ll*x*x%mod;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ll _2=qpow(2,mod-2);
ll up=2,_down=_2;
f[1]=_2;
for(int i=2;i<=maxn-1;++i){
up=up*2%mod;
_down=_down*_2%mod;
f[i]=(up-1)*_down%mod*f[i-1]%mod;
}
for(int i=2;i<=maxn-1;++i)
f[i]=f[i]^f[i-1];
int t;cin>>t;
while(t--){
int n;cin>>n;
cout<<f[n]<<endl;
}
return 0;
}