2020牛客暑期多校训练营Binary Vector(线性独立,递推,乘法逆元)

Binary Vector

题目描述

2020牛客暑期多校训练营Binary Vector(线性独立,递推,乘法逆元)_第1张图片

输入描述:

2020牛客暑期多校训练营Binary Vector(线性独立,递推,乘法逆元)_第2张图片

输出描述:

在这里插入图片描述

示例1

输入

3
1
2
3

输出

500000004
194473671
861464136

说明

2020牛客暑期多校训练营Binary Vector(线性独立,递推,乘法逆元)_第3张图片

题目大意

给你一个 n n n,并在 n n n维度里有一些向量,这些向量的每一维都是由 0 , 1 0,1 0,1构成的。现在,每一天都取一个向量,求 n n n天中,取到的所有向量都是线性独立的的概率 f ( n ) f(n) f(n)是多少。
题目要求输出 f ( 1 ) ⊕ f ( 2 ) ⊕ f ( 3 ) . . . ⊕ f ( n ) f(1)\oplus f(2)\oplus f(3)...\oplus f(n) f(1)f(2)f(3)...f(n)的值 m o d   1 e 9 + 7 mod\,1e9+7 mod1e9+7

分析

首先理解下什么叫做线性独立。说白了,就是说任意一个向量都不能通过其他向量的加减得到,那么也就是说,每个向量都不共面。

起初,考虑每个维度最多有多少01向量。很容易可以发现,一维只有向量(0)和(1),二维有(0,0)(0,1)(1,0)(1,1),三维就有8个…… n n n维就有 2 n 2^n 2n个01向量。

考虑选取 i i i个向量
首先,我们从 i = 1 i=1 i=1的简单情况开始考虑。在一根一维的线中,也就是数轴,对于向量 a ⃗ \vec{a} a ,只有 0 ⃗ \vec{0} 0 a ⃗ \vec{a} a 本身不是 a ⃗ \vec{a} a 线性独立的
据此,考虑 i = 2 i=2 i=2,在平面中,如果选了 a ⃗ , b ⃗ \vec{a},\vec{b} a ,b ,那么除了它们本身和 0 ⃗ \vec{0} 0 以外,还有 a ⃗ + b ⃗ \vec{a}+\vec{b} a +b 也是不与 a ⃗ , b ⃗ \vec{a},\vec{b} a ,b 线性独立的。有 4 4 4个。
同样的,当 i = 3 i=3 i=3时,就有 8 8 8个不与选出来的3个向量独立。
⋮ \vdots
可以推断,对于 i i i,有 2 i 2^i 2i个向量是不与选得的向量独立的。

那么,如果在一个 n n n维度的空间里,选取 i i i个向量有共面的概率是 2 i 2 n \cfrac{2^i}{2^n} 2n2i。所以不共面也就是都是线性独立的概率是 2 n − 2 i 2 n {\cfrac{2^n-2^i}{2^n}} 2n2n2i
因此有
f ( n ) = ∏ i = 1 n 2 n − 2 i 2 n f(n)=\mathop{\prod}\limits_{i=1}^n \cfrac{2^n-2^i}{2^n} f(n)=i=1n2n2n2i
   = ∏ i = 1 n 2 n − i − 2 0 2 n − i \qquad\,\,=\mathop{\prod}\limits_{i=1}^n \cfrac{2^{n-i}-2^0}{2^{n-i}} =i=1n2ni2ni20
   = ∏ i = 1 n 2 i − 1 2 i \qquad\,\,=\mathop{\prod}\limits_{i=1}^n \cfrac{2^{i}-1}{2^{i}} =i=1n2i2i1
于是 f ( n ) f(n) f(n)就可以通过 f ( i ) f(i) f(i)递推过来。

代码

#include
#define ll long long
using namespace std;
const int MAXN=2e7;
const int mod=1e9+7;
int T,n,mul[MAXN],inv[MAXN],ans[MAXN];
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);//先用费小求inv
    for(int i=MAXN-1;i>0;i--) inv[i]=2ll*inv[i+1]%mod;//然后递推求inv
    int x=inv[1];ans[1]=inv[1];
    for(int i=2;i<=N;i++)
		x=1ll*x*(mul[i]-1)%mod*inv[i]%mod,//递推求答案
		ans[i]=ans[i-1]^x;//XOR后输出,打表完毕
    scanf("%d",&T);
    while(T--) scanf("%d",&n),printf("%d\n",ans[n]);
}

END

队友肝的,%%%。

你可能感兴趣的:(2020牛客多校,线性独立,递推,乘法逆元)