csp-s模拟测试66
考试思考!!
T1:听说是错排,但我没见过,现刚的。
显然先任意放再去不合法比较好搞。
就是$n!$每一行每一列的对应情况。
然后要去掉放在黑点上的情况。
先看至少有一个放重的情况$(n-1)!$但是我如果以每个重点考虑一次的话,我的状态就不符合定义了,
即$C(n,1)*(n-1)!$就不是至少有一个的情况了,显然算重了许多,
那么设$f(n)$为n个元素的集合按照乘组合数以后被算重的次数。
$f(n)=\sum \limits_{i=1}^{n-1}C(n,i)$就是在计算所有比他小的集合时都在那时乘的C就是多算的。
接下来观察这个柿子,某些大佬在某些项上添加了一些系数。
$f(n)=\sum \limits_{i=1}^{n-1}(-1)^{i+1}C(n,i)$然后就相当于,在集合为某些大小的时候修正我的错误计算方法,能得到正确的值
至于正确性,二项式定律化一下就好了。
好了这就是我理解的容斥原理。
当然没脑残哥写的好推荐一发
#include<iostream> #include<cstdio> #include<cstring> using std::cout; using std::endl; using std::max; const int N=210,cu=1e4; int a[N][N]; inline int rd() { int s=0,w=1; char cc=getchar(); for(;cc<'0'||cc>'9';cc=getchar()) if(cc=='-') w=-1; for(;cc>='0'&&cc<='9';cc=getchar()) s=(s<<3)+(s<<1)+cc-'0'; return s*w; } struct hint { int bin[220]; int &operator [](int i) {return bin[i];} void clear(){memset(bin,0,sizeof(bin));} hint friend operator *(hint a,hint b) { hint c;c.clear(); int i=1,x=0; for(i=1;i<=a[0]+1;i++) { for(int j=1;j<=b[0]+1;j++) { c[i+j-1]=c[i+j-1]+a[i]*b[j]+x; x=c[i+j-1]/cu; c[i+j-1]%=cu; //cout<<i<<" "<<j<<" "<<c[i+j-1]<<endl; } } c[0]=a[0]+b[0]+2; while(c[c[0]]==0&&c[0]>1) c[0]--; return c; } hint friend operator +(hint a,hint b) { int i=1,x=0;hint c;c.clear(); while(i<=a[0]+1||i<=b[0]+1) { c[i]=a[i]+b[i]+x; x=c[i]/cu; c[i]%=cu; i++; } c[0]=a[0]+b[0]+1; while(c[c[0]]==0&&c[0]>1) c[0]--; return c; } void operator -=(hint b) { int x=0; for(int i=1;i<=bin[0];i++) { if(bin[i]<b[i]) bin[i+1]--,bin[i]+=cu; bin[i]-=b[i]; } while(bin[bin[0]]==0&&bin[0]>1) bin[0]--; } void print() { printf("%d",bin[bin[0]]); for(int i=bin[0]-1;i;i--) printf("%04d",bin[i]); puts(""); } }fac[N],C[N][N]; int main() { int n=rd(); for(register int i=1;i<=n;i++) for(register int j=1;j<=n;j++) a[i][j]=rd(); C[0][0][0]=1;C[0][0][1]=1; for(int i=1;i<=n;i++) { C[i][0][0]=1;C[i][0][1]=1; for(int j=1;j<=i;j++) { C[i][j]=C[i-1][j]+C[i-1][j-1]; } } fac[0][0]=1;fac[0][1]=1; for(int i=1;i<=n;i++) { hint c;c.clear();c[0]=1,c[1]=i; fac[i]=fac[i-1]*c; } hint ans=fac[n]; //ans.print(); for(int i=2;i<=n;i+=2) { ans=ans+C[n][i]*fac[n-i]; } for(int i=1;i<=n;i+=2) { ans-=C[n][i]*fac[n-i]; } ans.print(); } /* g++ 1.cpp -std=c++11 -o 1 time ./1 20 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 */
T2:好题,性质题。
Zeit und Raum trennen dich und mich.时空将你我分开。