Binary Vector
题目描述:
设
A
A
A
=
=
=
{
\{
{
0
,
1
0,1
0,1
}
\}
},每天
R
o
u
n
d
g
o
d
Roundgod
Roundgod从
A
n
A^n
An
(
(
( 即维度为n,每一位由01组成的所有向量的集合
)
)
)中随机选择一个二进制向量。现在他想知道n天中选取n个线性独立向量的概率。请告诉
R
o
u
n
d
g
o
d
Roundgod
Roundgod每个排列的答案,用
P
⋅
Q
−
1
P⋅Q^{-1}
P⋅Q−1
(
(
(
m
o
d
mod
mod
1
0
9
+
7
10^9+7
109+7
)
)
)表示。其中
Q
−
1
Q^{-1}
Q−1是
Q
Q
Q模
1
0
9
+
7
10^9+7
109+7的乘法逆元。
设
f
n
f_n
fn表示
n
n
n的答案,最后输出
f
1
f_1
f1
⊕
\oplus
⊕
f
2
f_2
f2
⊕
\oplus
⊕
.
.
.
...
...
⊕
\oplus
⊕
f
n
f_n
fn,
⊕
\oplus
⊕表示异或。
线性独立介绍
对于问题
B
B
B,
A
n
A^n
An是仅包含
0
0
0和
1
1
1的
n
n
n维向量
输入描述:
输入包含多个测试用例。 输入的第一行包含一个整数 T T T ( ( ( 1 1 1 ≤ \le ≤ T T T ≤ \le ≤ 1000 1000 1000 ) ) ),表示测试用例的数量。在接下来的 T T T行中,每行包含一个整数 N N N ( ( ( 1 1 1 ≤ \le ≤ N N N ≤ \le ≤ 2 ∗ 1 0 7 2*10^7 2∗107 ) ) ),描述一个测试用例。
输出描述:
对于每个测试用例,输出一个整数来表示答案。
样例输入:
3
1
2
3
样例输出:
500000004
194473671
861464136
说明:
f(1)=1/2
f(2)=3/8
f(3)=21/64
思路:
暴力出奇迹,打表出省一
打表。
打
2
e
7
2e7
2e7的表。
首先讲一下线性独立,就是说:任意一个向量都不能通过其他向量加减得到,也就是所有的向量都不共面
考虑选取
i
i
i个向量,对于
i
i
i,有
2
i
2^i
2i个向量是不与选择的向量独立
那么在一个
n
n
n维的空间内,选取
i
i
i个向量共面的概率是
2
i
2
n
\frac{2^i}{2^n}
2n2i
那么 n n n维的空间内,选取 i i i个向量线性独立的概率就是 2 n − 2 i 2 n \frac{2^n-2^i}{2^n} 2n2n−2i
所以:
f
n
=
f_n=
fn=
∏
i
=
0
n
−
1
\mathop{\prod}\limits_{i=0}^{n-1}
i=0∏n−1
2
n
−
2
i
2
n
\frac{2^n-2^i}{2^n}
2n2n−2i
=
=
=
∏
i
=
0
n
−
1
\mathop{\prod}\limits_{i=0}^{n-1}
i=0∏n−1
2
n
−
i
−
1
2
n
−
i
\frac{2^{n-i}-1}{2^{n-i}}
2n−i2n−i−1
=
=
=
∏
i
=
0
n
−
1
\mathop{\prod}\limits_{i=0}^{n-1}
i=0∏n−1
2
i
−
1
2
i
\frac{2^i-1}{2^i}
2i2i−1
这样我们就可以打表了。
AC Code:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e7+5;
const int mod=1e9+7;
int T,n,mul[MAXN],inv[MAXN],ans[MAXN],x;
int ksm(int a,int b)
{
int r=1;
while(b)
{
if(b&1) r=1ll*r*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return r;
}
int main()
{
mul[0]=1;
for(int i=1;i<=MAXN;i++)
mul[i]=2ll*mul[i-1]%mod;
inv[MAXN]=ksm(mul[MAXN],mod-2);
for(int i=MAXN-1;i;i--)
inv[i]=2ll*inv[i+1]%mod;
ans[1]=x=inv[1];
for(int i=2;i<=MAXN;i++)
{
x=1ll*x*(mul[i]-1)%mod*inv[i]%mod;
ans[i]=ans[i-1]^x;
}
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%d\n",ans[n]);
}
}