hdu 6397 Character Encoding

hdu 6397 Character Encoding

Problem Description
In computer science, a character is a letter, a digit, a punctuation mark or some other similar symbol. Since computers can only process numbers, number codes are used to represent characters, which is known as character encoding. A character encoding system establishes a bijection between the elements of an alphabet of a certain size n and integers from 0 to n1. Some well known character encoding systems include American Standard Code for Information Interchange (ASCII), which has an alphabet size 128, and the extended ASCII, which has an alphabet size 256.

For example, in ASCII encoding system, the word wdy is encoded as [119, 100, 121], while jsw is encoded as [106, 115, 119]. It can be noticed that both 119+100+121=340 and 106+115+119=340, thus the sum of the encoded numbers of the two words are equal. In fact, there are in all 903 such words of length 3 in an encoding system of alphabet size 128 (in this example, ASCII). The problem is as follows: given an encoding system of alphabet size n where each character is encoded as a number between 0 and n1 inclusive, how many different words of length m are there, such that the sum of the encoded numbers of all characters is equal to k?

Since the answer may be large, you only need to output it modulo 998244353.

 

Input
The first line of input is a single integer T (1T400), the number of test cases.

Each test case includes a line of three integers n,m,k (1n,m105,0k105), denoting the size of the alphabet of the encoding system, the length of the word, and the required sum of the encoded numbers of all characters, respectively.

It is guaranteed that the sum of n, the sum of m and the sum of k don't exceed 5×106, respectively.

 

Output
For each test case, display the answer modulo 998244353 in a single line.

 

Sample Input
4 2 3 3 2 3 4 3 3 3 128 3 340

 

Sample Output
1 0 7 903

 

Source
 

题意:

  共有m个取值范围为[0,n-1]的数字,求使得总和为k的方案数,即求

的整数解的组数

 

 

思路:

     我们可以把k看成k个1,通过m-1个隔板来分割成m个数字。但是这样做会有问题,就是数字可能为0,但是隔板法不允许这种情况存在,所以我们可以做一个等价处理,即将取值范围+1,即[1,n],那么相应的总和也要加上m,即k+m,则问题转化为 “共有m个取值范围为[1,n]的数字,求使得总和为m+k的方案数”, 根据隔板法可以得出无限制的情况下方案数为 C(m+k-1, m-1)。

    而题目的限制是 Xi<=n,假设我们先从总和(m+k)取出n,然后把剩下的部分(m+k-n)分成m份,那么此时再把预先取出的n放到这m份中的任意一份中,都会使得它大于n,即超出了限制,所以这次种情况至少会使得一个数超出限制。那假设我们预先取出了2*n呢?同理,这种情况至少会使得两个数超出限制,以此类推直到c不满足c*n<=k的条件。那么根据容斥原理,答案就是:

 

注意要预处理出阶乘,以及阶乘的逆元,这样就可以O(1)得到组合数,不然会超时

代码:

 

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;

typedef long long ll;
const int MAXN = 2e5+40;
const ll mod = 998244353;
ll fac[MAXN],ifac[MAXN],inv[MAXN];


void init()
{
    int n = MAXN;
    inv[1]=1;
    for(int i=2;i<n;i++)///预处理逆元
    {
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
    fac[0]=1;
    ifac[0]=1;
    for(int i=1;i<n;i++)///预处理阶乘和阶乘的逆
    {
        fac[i]=fac[i-1]*i%mod;
        ifac[i]=ifac[i-1]*inv[i]%mod;
    }

}


ll C(int n,int m )
{
    if(n<0||m<0||n<m) return 0;              ///没有这句导致 wa了
    return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}

int main()
{

    int t,n,m,k;
    init();
    scanf("%d", &t);
    while(t--){
        scanf("%d%d%d", &n, &m, &k);
        ll  ans = 0;
        for(int c=0;c*n<=k;c++){
            if(c&1){
                ans = (ans-C(m,c)*C(m-1+k-c*n,m-1)%mod+mod)%mod;
            }else{
                ans = (ans+C(m,c)*C(m-1+k-c*n,m-1)%mod)%mod;
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

 

 

posted @ 2018-08-17 14:50  BrysonChen  阅读(335)  评论(0编辑  收藏  举报