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
*/
View Code

    T2:好题,性质题。

猜你喜欢

转载自www.cnblogs.com/starsing/p/11674390.html