2020牛客暑期多校训练营第六场Binary Vector(数学,打表)

题目

传送门

题目大意

A = { 0 , 1 } A=\{0,1\} A={0,1},从 A n ( A^n ( An( 维度为 n n n,由 01 01 01组成的向量全集 ) ) )中随机选取一个。现在他想知道 n n n天中选取 n n n个线性独立向量的概率。请告诉 R o u n d g o d Roundgod Roundgod每个排列的答案,用 P ⋅ Q − 1 ( m o d 1 0 9 + 7 ) P⋅Q^{-1}(mod 10^9+7) PQ1(mod109+7)表示。其中 Q − 1 Q^{-1} Q1 Q Q Q 1 0 9 + 7 10^9+7 109+7的乘法逆元。设 f n f_n fn表示维度为 n n n时的答案,最后输出 f 1 ⊕ f 2 ⊕ . . . . . . ⊕ f n f_1\oplus f_2\oplus ......\oplus f_n f1f2......fn ⊕ \oplus 表示异或。 A n A^n An是仅包含 0 0 0 1 1 1 n n n维向量

分析

一看这题就知道肯定有公式可循,果断暴力,然后推公式:
在本题的条件下,不难得出以下结论:

当选取 i i i个向量时,共有 2 i 2^i 2i个向量不与选择的向量线性独立

(如果觉得难以得出请不要偷懒,老老实实看一下前文的超链接,好好理解什么是线性独立)

由上得:
在一个 n n n维空间里,选取 i i i个向量线性独立的概率就是 2 n − 2 i 2 n \frac{2^n-2^i}{2^n} 2n2n2i

f n = ∏ i = 0 n − 1 2 n − 2 i 2 n f_n=\prod\limits _{i=0}^{n-1}\frac{2^n-2^i}{2^n} fn=i=0n12n2n2i

这个公式看着头疼,化简一下:

原式 = ∏ i = 0 n − 1 2 n − i − 1 2 n − i =\prod\limits _{i=0}^{n-1}\frac{2^{n-i}-1}{2^{n-i}} =i=0n12ni2ni1
= ∏ i = 0 n − 1 2 i − 1 2 i =\prod\limits _{i=0}^{n-1}\frac{2^i-1}{2^i} =i=0n12i2i1
有了这个公式,我们便可以开始打表了

代码

#include 

const int MAXN=2e7,mod=1e9+7;
int T,n,base[MAXN],inv[MAXN],ans[MAXN];

int ksm(int x,int p)
{
    int ret=1;
    while(p)
	{
		if(p&1) ret=1ll*ret*x%mod;
		x=1ll*x*x%mod;
		p>>=1;
	}
    return ret;
}

void work()
{
	base[0]=1;
    for(int i=1;i<=MAXN;i++) base[i]=2ll*base[i-1]%mod;
    inv[MAXN]=ksm(base[MAXN],mod-2);
    for(int i=MAXN-1;i;i--) inv[i]=2ll*inv[i+1]%mod;
    int x=inv[1];
	ans[1]=inv[1];
    for(int i=2;i<=MAXN;i++) x=1ll*x*(base[i]-1)%mod*inv[i]%mod,ans[i]=ans[i-1]^x;
}

int main()
{
    work();for(scanf("%d",&T);T--;) scanf("%d",&n),printf("%d\n",ans[n]);
}

----原创文章,仅供参考

你可能感兴趣的:(2020牛客暑期多校训练营第六场Binary Vector(数学,打表))