线性代数 向量 秩 2020牛客暑期多校训练营(第六场)Binary Vector
题目大意:
给出一个 n * n 的 01 矩阵,求满秩的概率
题解:
对于第一个只要不全为0即可,方案是:\(2^n-1\)
对于第二个只要不全为0,且不被第一个表示即可,方案数:\(2^n-2\)
对于第三个只要不全为0,并且不被第一个第二个表示即可,方案数:\(2^n-4\)
...
对于最后一个的方案数:\(2^n- 2^{n-1}\)
直接相乘:$\prod_{i=0}^{i=n-1} (2^n-2^i) $
每一个的所有总方案数都是 \(2^n\) ,相乘得 \(2^{n^2}\)
所以最后的概率是 :\(\frac{\prod_{i=0}^{i=n-1} (2^n-2^i)}{2^{n^2}}\)
但是这个式子要进行优化,才可以得出解:
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
#define debug(x) printf("debug:%s=%lld\n",#x,x);
using namespace std;
typedef long long ll;
const int maxn = 2e7+10;
const int mod = 1e9+7;
ll f[maxn],ans[maxn];
void init(){
ll inv = 500000004;
f[1] = ans[1] = inv;
ll up = 2,down = inv;
for(int i=2;i<maxn;i++){
up=up*2%mod;
down = down*inv%mod;
f[i]=(up-1+mod)%mod*down%mod*f[i-1]%mod;
ans[i]=f[i]^ans[i-1];
}
}
int main(){
init();
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
printf("%lld\n",ans[n]);
}
}