HDU 2049 神、上帝以及老天爷 错排

来源:互联网 发布:阿里云储存空间不足 编辑:程序博客网 时间:2024/06/02 01:55

题意就是:有n个人,然后每个人不能拿到和自己编号相同的字条
错排:对于第一个位子,有n-1种方法,我们假设放了k,然后对于k的位子,我们如果放了1的话,之后就是对于n-2的错排。如果1不放到k,就可以把k的位置看成“第1个位置”,然后就是n-1的错排
f(n)=(n-1)*(f(n-1)+f(n-2))
参考http://blog.csdn.net/cambridgeacm/article/details/7722708

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>using namespace std;const int maxn = 25;long long f[maxn];long long x[maxn];void ini(){    f[1]=0;    f[2]=1;    f[3]=2;    x[0]=1;    for(int i=4;i<=20;i++)        f[i]=(i-1)*(f[i-1]+f[i-2]);    for(int i=1;i<=20;i++)        x[i]=i*x[i-1];}int main(){    int C;    scanf("%d",&C);    ini();    while(C--)    {        int n;        scanf("%d",&n);        printf("%.2f%%\n",(double)f[n]*100/(double)x[n]);    }    return 0;}

然后用容斥原理也可以做
d=(1-1/1!+1/2!-1/3!…….+(-1)^n/n!);
就把这个式子求出来就行了

#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>using namespace std;#define LL long longconst int maxn = 25;LL A[maxn];void init(){    A[0]=1;    A[1]=1;    for(int i=2;i<=20;i++)        A[i]=A[i-1]*i;    return ;}int main(){    int t;    scanf("%d",&t);    init();    while(t--)    {        int n;        scanf("%d",&n);        double ans=1;        for(int i=1;i<=n;i++){        if(i%2==1)        ans-=(double)1/A[i];        else ans+=(double)1/A[i];        }        printf("%.2f%%\n",ans*100);    }    return 0;}
0 0