• [HDU6397] Character Encoding


    前言

    挺好一道数学题,适合我这种数学刚入门的蒟蒻做

    题目

    HDU

    题目大意:给定正整数(n,m,k)

    (x_1+x_2+...+x_m=k (0 le x_i<n))的解的个数

    答案对(998244353)取模

    讲解

    首先我们考虑如果没有(x_i<n)这个限制,答案应该是多少

    明显可以用隔板法求出答案为(C(k+m-1,m-1))

    接下来我们考虑减掉不合法的方案数

    对于恰好有一个数不合法,两个数不合法...都要减掉

    明显这很麻烦,所以很容易想到容斥

    我们只需钦定(i)个数不合法,给它们在最开始便加上(n)即可

    此时的方案数为(C(m,i)),剩余的(k-n*i)我们可以用隔板法求出方案数,然后再乘上容斥系数即可

    所以对于一个确定的(i),它对答案的贡献为((-1)^{i} * C(m,i) * C(k-n*i+m-1,m-1))

    注意:

    1.你细品(C(k-n*i+m-1,m-1))的式子,仔细想想预处理阶乘的数组要开多大

    2.最后的答案可能是负数,记得处理

    代码

    LL qpow(LL x,LL y,int MOD)
    {
    	LL ret = 1;y %= (MOD-1);
    	while(y){if(y & 1) ret = ret * x % MOD;x = x * x % MOD;y >>= 1;}
    	return ret;
    }
    
    int fac[MAXN],ifac[MAXN];
    void pre(int x)
    {
    	fac[0] = 1;
    	for(int i = 1;i <= x;++ i) fac[i] = 1ll * fac[i-1] * i % MOD;
    	ifac[x] = qpow(fac[x],MOD-2,MOD);
    	for(int i = x-1;i >= 0;-- i) ifac[i] = 1ll * ifac[i+1] * (i+1) % MOD;
    }
    LL C(LL x,LL y)
    {
    	if(x < y) return 0;
    	return 1ll * fac[x] * ifac[y] % MOD * ifac[x-y] % MOD;
    }
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	pre(200000);
    	for(int T = Read(); T ;T --)
    	{
    		n = Read(); m = Read(); k = Read();
    		//x1+x2+..xm=k xi<n
    		LL ans = 0;
    		for(int i = 0;i <= m;++ i)
    		{
    			LL f = (i&1) ? -1 : 1;
    			ans = (ans + f * C(m,i) * C(k-n*i+m-1,m-1) % MOD) % MOD;
    		}
    		Put((ans + MOD) % MOD,'
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    16.检查是否为BST
    15.输出单层结点
    14.高度最小的BST
    *13.有向路径检查
    12.二叉树平衡检查
    11.双栈排序
    10.回文链表
    9.链式A+B
    8.链表分割
    7.访问单个节点的删除
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13625596.html
Copyright © 2020-2023  润新知