zoukankan      html  css  js  c++  java
  • 错排问题

    源代码:
    
    #include<cstdio>
    #define LL long long
    #define INF 1000000007
    LL m,n,Num(0),i[100001],Sum[100001];
    bool Vis1[100001]={0},Vis2[100001]={0};
    LL M(LL t) //取模,注意负数。
    {
        if (t>=0&&t<INF)
          return t;
        t%=INF;
        if (t<0)
          t+=INF;
        return t;
    }
    LL Count(LL X,LL S) //快速幂。
    {
        LL Number=1;
        while (S)
        {
            if (S&1)
              Number=(Number*X)%INF;
            X=(X*X)%INF;
            S>>=1;
        }
        return Number;
    }
    LL C(LL n,LL m)
    {
        if (n<m||!n)
          return 0;
        return i[n]*Sum[n-m]%INF*Sum[m]%INF;
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        i[0]=1;
        for (LL a=1;a<=n;a++)
          i[a]=i[a-1]*a%INF;
        for (LL a=0;a<=n;a++)
          Sum[a]=Count(i[a],INF-2);
        for (LL a=1;a<=m;a++)
        {
            LL t1,t2;
            scanf("%lld%lld",&t1,&t2);
            if (t1==t2)
            {
                printf("0");
                return 0;
            }
            Vis1[t1]=Vis2[t2]=true;
        }
        LL Ans=i[n-m];
        for (LL a=1;a<=n;a++)
          if (!Vis1[a]&&!Vis2[a])
            Num++;
        for (LL a=1;a<=Num;a++)
          if (a&1)
            Ans=M(Ans-C(Num,a)*i[n-m-a]);
          else
            Ans=(Ans+C(Num,a)*i[n-m-a])%INF;
        printf("%lld",Ans);
        return 0;
    }
    
    /*
        一道NOIP阶段比较全面的排列组合题。
        原始的错排公式:
            (1)通过CodeVS ⑨要写信 可以得出递推公式:
                f[i]=(i-1)(f[i-1]+f[i-2])
            (2)n个数的全排列个数为n!,其中第k位为k的个数为(n-1)!,那么对于n个数,共有n(n-1)!为放对一个的,则减去;
               但会把两个数放对的多减一次,则加上C(n,2)*(n-2)!;
               但会把三个数放对的多加一次,则减去C(n,3)*(n-3)!;
               以此类推,最终可得错排公式:
                    Ans=n!-C(n,1)*(n-1)!+C(n,2)*(n-2)!-C(n,3)*(n-3)!+...+(-1)^n*C(n,n)*(n-n)!
                       =∑(k=0~n)(-1)^k*C(n,k)*(n-k)!
               其实就是容斥原理。
        现行的错排公式:
            仿照以上,设s为剩下的(n-m)个数仍有可能放到正确位置的个数,则有:
                Ans=(n-m)!-C(s,1)*(n-m-1)!+C(s,2)*(n-m-2)!+...+(-1)^s*C(s,s)*(n-m-s)!
                   =∑(k=0~s)(-1)^k*C(s,k)*(n-m-k)!
            排列组合如此神奇。
    */
  • 相关阅读:
    C# Win7系统下为应用程序取得管理员权限
    bootstrap 列函数
    bootstrap table offset 参数问题
    java 调用webservcie ,自己亲测可用
    sqlserver 生成数据字典
    css 色彩大全网址
    C#遍历指定文件夹中的所有文件和子文件夹
    ajax 跨域调用webservice 使用jsonp解决方法
    XML 类型数据转化为表
    SQL SERVER 查询未提交的事务
  • 原文地址:https://www.cnblogs.com/Ackermann/p/6037356.html
Copyright © 2011-2022 走看看