• HDU


    题意:T组数据,给次给出N,M,K,多少种方案,用[0,N-1]范围的数,表示一个M排列,其和为K;

    思路:隔板法,不限制[0,N-1]的时候答案是C(M+K-1,M-1);那么我们减去至少一个>=N,加上至少两个>=N....即可得到答案。

    假设至少一个隔板里的数大于大于N,我们从这个隔板里抽出N即可,其方案数为C(M+K-1-N,M-1)*(M,1),符号为-1;

    假设至少两个隔板里的数大于大于N,我们从这两个隔板里抽出N即可,其方案数为C(M+K-1-2*N,M-1)*(M,2),符号为1;

    ....

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=200010;
    const int Mod=998244353;
    int f[maxn],inv[maxn];
    int qpow(int a,int x){
        int res=1; while(x){
            if(x&1) res=(ll)res*a%Mod;
            x>>=1; a=(ll)a*a%Mod;
        } return res;
    }
    int C(int n,int m){
        if(m>n||n<0||m<0) return 0;
        return (ll)f[n]*inv[m]%Mod*inv[n-m]%Mod;
    }
    int main()
    {
        f[0]=inv[0]=1;
        for(int i=1;i<=200000;i++) f[i]=(ll)f[i-1]*i%Mod;
        inv[200000]=qpow(f[200000],Mod-2);
        for(int i=199999;i>=1;i--) inv[i]=(ll)inv[i+1]*(i+1)%Mod;
        int T,N,M,K;
        scanf("%d",&T);
        while(T--){
            int ans=0,opt=1;
            scanf("%d%d%d",&N,&M,&K);
            for(int i=0;i<=M&&i*N<=K;i++){
                (((ans+=(ll)opt*C(M+K-i*N-1,M-1)*C(M,i)%Mod)%=Mod)+=Mod)%=Mod;
                opt=-opt;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    v-cloak
    MVVM
    初识ajax
    装瓶学习法
    回调函数(call back)
    如何让学习变得纯粹?
    异步
    grep用法
    Shell中的&&与||的区别
    shell中使用>/dev/null 2>&1 丢弃信息
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9888137.html
Copyright © 2020-2023  润新知