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的方案数,即求php

的整数解的组数c++

 

 

思路:

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

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

 

注意要预处理出阶乘,以及阶乘的逆元,这样就能够O(1)获得组合数,否则会超时this

代码:

 

#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;
}
相关文章
相关标签/搜索