zoukankan      html  css  js  c++  java
  • K

    N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, numbered from 1 to n(Wand_i owned by wizard_i). After the meeting, n wizards will take a wand one by one in the order of 1 to n. A boring wizard decided to reorder the wands. He is wondering how many ways to reorder the wands so that at least k wizards can get his own wand.

    For example, n=3. Initially, the wands are w1 w2 w3. After reordering, the wands become w2 w1 w3. So, wizard 1 will take w2, wizard 2 will take w1, wizard 3 will take w3, only wizard 3 get his own wand.

    Input

    First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

    For each test case: Two number n and k.

    1<=n <=10000.1<=k<=100. k<=n.

    Output

    For each test case, output the answer mod 1000000007(10^9 + 7).

    Sample Input

    2
    1 1
    3 1
    

    Sample Output

    1
    4
    题解:n个人排位,求至少k个人能做到自己位置的方法树。那么我们就要求出组合数Cnm,错排递推数组dp[i],
    然后还有数据的问题,要反向考虑,从k到n转换为从0到k(左闭右开),那么还要计算出排列递推数组fac[i](即阶乘)位总方案数,一减即得答案。
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int maxn=10010;
    const int mod=1e9+7;
    ll C[maxn][105],dp[maxn],fac[maxn];
    void Init()
    {
        fac[0]=1,fac[1]=1;
        for(int i=2;i<=10000;i++)//计算总方案数,即阶乘数
            fac[i]=i*fac[i-1]%mod;
        dp[0]=1,dp[1]=0,dp[2]=1;
        for(int i=3;i<=10000;i++)//错排公式
        {
            dp[i]=((i-1)*(dp[i-1]+dp[i-2])%mod)%mod;;
        }
        C[1][0]=1;
        C[1][1]=1;
        for(int i=2;i<=10000;i++)//组合公式
        {
            C[i][0]=1;
            for(int j=1;j<=i&&j<=100;j++)
            {
                C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
            }
        }
    }
    int main()
    {
        std::ios::sync_with_stdio(0);
        Init();
        int t,n,k;
        cin>>t;
        while(t--)
        {
            cin>>n>>k;
            ll ans=0;
            for(int i=0;i<k;i++)//由于正向考虑会T,并且k<100,那么我们反向考虑情况,用总情况减去即可
            {                   //反向情况即为:从n个数中选取i个,剩下n-i个错排,i范围从0到k
                ans=(ans+(C[n][i]*dp[n-i])%mod)%mod;
            }
            cout<<(fac[n]-ans+mod)%mod<<endl;//注意输出也要取模
        }
        return 0;
    }
  • 相关阅读:
    BZOJ2002 [HNOI2010] 弹飞绵羊
    BZOJ1030 [JSOI2007] 文本生成器
    BZOJ3233 [AHOI2013] 找硬币
    BZOJ4269 再见xor
    BZOJ5297 CQOI2018 社交网络
    LOJ149 0/1分数规划
    BZOJ2132 圈地计划
    UOJ131 [NOI2015] 品酒大会
    composer速度慢(composer更换国内镜像)
    thinkphp6安装报错,composer install tp6 报错 Parse error: syntax error
  • 原文地址:https://www.cnblogs.com/cherish-lin/p/10699318.html
Copyright © 2011-2022 走看看