CF1530F
正难则反,考虑计算每条线都不全为一的概率 \(P\)
对角线很烦,考虑先 \(2^2\) 容斥掉,直接把概率改为一即可
于是就有了一个暴力容斥的解法:钦定全为一的行列集合 \(S\),则 \(P=\sum_{S}(-1)^{\lvert S\rvert}\prod_{(i,j)\in S}p_{i,j}\),时间复杂度 \(O(2^{2n}n^2)\)
考虑将行分出来,设全为一的行集合为 \(S_1\),全为一的列集合为 \(S_2\),则 \(P=\sum_{S_1}\sum_{S_2}(-1)^{\lvert S_1\rvert+\lvert S_2\rvert}\prod_{i\in S_1\lor j\in S_2}p_{i,j}\)
\(=\sum_{S_1}(-1)^{\lvert S_1\rvert}(\prod_{i\in S_1}p_{i,j})\sum_{S_2}(-1)^{\lvert S_2\rvert}\prod_{j\in S_2\land i\notin S_1}p_{i,j}\)
设 \(g_{j,S}=\prod_{i\notin S}p_{i,j},f_{S}=(-1)^{\lvert S\rvert}\prod_{i\in S}p_{i,j}\)
\(=\sum_{S_1}f_{S_1}\sum_{S_2}(-1)^{\lvert S_2\rvert}\prod_{j\in S_2}g_{j,S_1}\)
设 \(G_{j,S}=-g_{j,S}\)
\(=\sum_{S_1}f_{S_1}\sum_{S_2}\prod_{j\in S_2}G_{j,S_1}\)
现在相当于有数列 \(a\),要求所有集合的元素积的和,答案是 \(\prod (a_i+1)\)
\(=\sum_{S_1}f_{S_1}\prod(G_{j,S_1}+1)\)
时间复杂度 \(O(n2^n)\)
#include<bits/stdc++.h>
using namespace std;
namespace ax_by_c{
const int mod=31607;
const int INV10000=3973;
const int N=23;
const int S=1<<22;
int lb(int x){
return x&(-x);
}
int n,p[N][N],mxst;
int pct[S],lg2[S];
int vis1[N],vis2[N];
int row[N];
int f[S],g[N][S];
int cal(){
for(int i=1;i<=n;i++){
row[i]=1;
for(int j=1;j<=n;j++){
row[i]=row[i]*p[i][j]%mod;
}
}
f[0]=1;
for(int i=1;i<=mxst;i++){
f[i]=f[i^lb(i)]*row[lg2[lb(i)]]%mod;
}
for(int i=0;i<=mxst;i++){
if(pct[i]%2==1){
f[i]=mod-f[i];
}
}
for(int j=1;j<=n;j++){
g[j][mxst]=1;
for(int s=mxst-1;s>=0;s--){
g[j][s]=g[j][s|lb(~s)]*p[lg2[lb(~s)]][j]%mod;
}
for(int s=0;s<=mxst;s++){
g[j][s]=mod-g[j][s];
}
}
int res=0;
for(int s=0;s<=mxst;s++){
int mul=1;
for(int j=1;j<=n;j++){
mul=mul*(g[j][s]+1)%mod;
}
res=(res+f[s]*mul)%mod;
}
return res;
}
void main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&p[i][j]);
p[i][j]=p[i][j]*INV10000%mod;
}
}
mxst=(1<<n)-1;
for(int i=1;i<=mxst;i++){
pct[i]=pct[i>>1]+(i&1);
}
for(int i=1;i<=n;i++){
lg2[1<<(i-1)]=i;
}
int P=0;
for(int x=0;x<=1;x++){
int mul=1;
if(x){
for(int i=1;i<=n;i++){
mul=mul*p[i][i]%mod;
vis1[i]=p[i][i];
p[i][i]=1;
}
}
for(int y=0;y<=1;y++){
int muls=mul;
if(y){
for(int i=1;i<=n;i++){
muls=muls*p[i][n-i+1]%mod;
vis2[i]=p[i][n-i+1];
p[i][n-i+1]=1;
}
}
if(x^y){
P=(P-muls*cal()%mod+mod)%mod;
}
else{
P=(P+muls*cal()%mod)%mod;
}
if(y){
for(int i=1;i<=n;i++){
p[i][n-i+1]=vis2[i];
}
}
}
if(x){
for(int i=1;i<=n;i++){
p[i][i]=vis1[i];
}
}
}
printf("%d\n",(1-P+mod)%mod);
}
}
int main(){
ax_by_c::main();
return 0;
}

浙公网安备 33010602011771号