UVALive 6469 Deranged Exams 组合数学+容斥原理

来源:互联网 发布:淘宝上买iphone店铺 编辑:程序博客网 时间:2024/04/30 05:47

这个题目的大概意思是:给n个座位。每个座位都有对应的人。问:至少前k个座位都坐错的种数。


直接求至少前k个座位都坐错的话有点难求。。

直接求总数-反例

把问题转换为:求至多有前k个座位坐对的总数。

假设有n=7 k=3

我们求前1个座位坐对的总数为:

C(3,1)*A(6,6)

但是考虑到这样的话会把1 3 1 2 2 3给算重

要减去1 2 1 3 2 3的总数。就是要减去C(3,2)*A(5,5)

但是减去的话又会多减去2 3的情况所以又要加上C(3,3)*A(4,4)

然后我们看一下

C(3,1)*A(6,6)-C(3,2)*A(5,5)+C(3,3)*A(4,4)


基本上就这样了。详情看代码

//First Edit Time:2014-07-15 19:15//Last Edit Time:2014-07-15 19:35//Filename:E.cpp#include <map>#include <set>#include <cmath>#include <queue>#include <stack>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#define LL long longusing namespace std;LL c[20][20];LL a[20];int main(){    a[0]=1;    a[1]=1;    c[1][0]=c[1][1]=1;    for(int i=2;i<=17;i++)    {        a[i]=a[i-1]*i;        c[i][0]=c[i][i]=1;        for(int j=1;j<i;j++)            c[i][j]=c[i-1][j]+c[i-1][j-1];    }    int t;    scanf("%d",&t);    while(t--)    {        int cas,n,k;        scanf("%d%d%d",&cas,&n,&k);        if(k==0)        {            printf("%d %lld\n",cas,a[n]);            continue;        }        LL  ans=0;        for(int i=1;i<=k;i++)        {            if(i&1) ans+=(c[k][i])*a[n-i];            else ans-=(c[k][i])*a[n-i];        }        printf("%d %lld\n",cas,a[n]-ans);    }    return 0;}



0 0
原创粉丝点击