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)!
            排列组合如此神奇。
    */
  • 相关阅读:
    2019安徽省程序设计竞赛 I.你的名字(序列自动机)
    poj3522Slim Span(暴力+Kruskal)
    Uva1349Optimal Bus Route Design(二分图最佳完美匹配)(最小值)
    基于Python的Web应用开发实战——3 Web表单
    [nRF51822]5.触摸按键
    [nRF51822]4.GPIO控制蜂鸣器
    [nRF51822]3. GPIO输入按键检测
    [nRF51822]2. 跑马灯
    [nRF51822]1. 点亮一个LED
    [nRF51822]0.nRF51822的开发环境
  • 原文地址:https://www.cnblogs.com/Ackermann/p/6037356.html
Copyright © 2011-2022 走看看