zoukankan      html  css  js  c++  java
  • 洛谷 P4071 [SDOI2016]排列计数

    洛谷

    这是一道组合数学题。

    对于一个长为n的序列,首先我们要选m个使之稳定(C^{m}_{n})

    且要保证剩下的序列不稳定,即错排(D_{n-m})

    所以答案就是:$$ANS=C^{m}{n}+D{n-m}$$

    再看看数据范围:n最大(10^6),错排好办,直接递推:

    [D[i]=(i-1)*(D[i-1]+D[i-2]) ]

    D[0]=1,D[1]=0。

    而组合数部分有点麻烦。$$C[i][j]=C[i-1][j]+C[i-1][j-1]$$

    用上面这个公式可以做1000的点,(n^2)递推。

    至于满分,我们可以用普通的组合数公式:$$C(n,m)=n!/[(n-m)!m!]$$

    我们预处理ni[]表示x的阶乘。

    接下来很好做了,除法取模涉及逆元,因为模数是质数,直接费马(t^{ exttt{mod}-2})

    所以代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int mo=1e9+7;
    int n,m;
    ll D[1000001]={1,0,1},ni[1000001]={1};
    
    void pre()
    {
        for (int i=3;i<=1000000;++i)
            D[i]=(i-1)*(D[i-1]+D[i-2])%mo;
        for (int i=1;i<=1000000;++i)
            ni[i]=ni[i-1]*i%mo;
    }
    
    ll qpow(ll x)
    {
        ll p=mo-2,d=1;
        while (p) {
            if (p&1) d=d*x%mo;
            x=x*x%mo;p>>=1;
        }
        return d;
    }
    
    int main()
    {
        pre();
        int T;cin>>T;
        while (T--) {
            scanf("%d%d",&n,&m);
            ll C=ni[n]*qpow(ni[m]*ni[n-m]%mo)%mo;
            printf("%lld
    ",C*D[n-m]%mo);
        }
        return 0;
    }
    
  • 相关阅读:
    lottie 动画
    .netcore 跨域问题
    数据库规范
    课程总结
    Beta版本发布
    个人作业-Alpha项目测试
    第三次作业结对编程
    第二次作业-熟悉使用工具
    第一次阅读作业
    个人作业-Alpha项目测试
  • 原文地址:https://www.cnblogs.com/fushao2yyj/p/9513275.html
Copyright © 2011-2022 走看看