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
 

Solution

这题有两种解法,一是std给的容斥,二是生成函数。

在0..n-1中选择m个数(可重复)使之和为k,这是一类整数拆分数问题,当n没有限制时,由隔板法可以得到ans=C(k+m-1,m-1)。好了容斥解法我还没看明白,容斥先鸽一割

进入正题谈谈生成函数,此题中,对于0..n-1这样一个序列每次它可以是选择其中一个数,其用生成函数表现为(1+x+x^2...+x^(n-1)),幂次即代表选择的是哪个数

那么对于m次选择,其随机可重复组合的生成函数g(x)=(1+x+x^2+...+x^(n-1))^m,生成函数中的幂级数是以形式幂级数理论为基础的,也就是说默认级数收敛。

f(x)=1+x+x^2+...+x^(n-1) => f(x)=(1-x^n)/(1-x), g(x)=(1-x^n)^m*(1-x)^(-m),对于这样一个式子,我们对前面一部分二项式展开可得

 


 

 1 #include <bits/stdc++.h>
 2 #define lson rt << 1, l, mid
 3 #define rson rt << 1 | 1, mid + 1, r
 4 using namespace std;
 5 using ll = long long;
 6 using ull = unsigned long long;
 7 using pa = pair<int, int>;
 8 using ld = long double;
 9 ll n, m, k;
10 const int maxn = 3e5 + 10;
11 const int mod = 998244353;
12 template <class T>
13 inline T read(T &ret)
14 {
15     int f = 1;
16     ret = 0;
17     char ch = getchar();
18     while (!isdigit(ch))
19     {
20         if (ch == '-')
21             f = -1;
22         ch = getchar();
23     }
24     while (isdigit(ch))
25     {
26         ret = (ret << 1) + (ret << 3) + ch - '0';
27         ch = getchar();
28     }
29     ret *= f;
30     return ret;
31 }
32 template <class T>
33 inline void write(T n)
34 {
35     if (n < 0)
36     {
37         putchar('-');
38         n = -n;
39     }
40     if (n >= 10)
41     {
42         write(n / 10);
43     }
44     putchar(n % 10 + '0');
45 }
46 ll fac[maxn], inv[maxn];
47 void init()
48 {
49     fac[0] = fac[1] = 1;
50     inv[0] = inv[1] = 1;
51     for (ll i = 2; i < maxn; i++)
52     {
53         fac[i] = fac[i - 1] * i % mod;
54         inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
55     }
56     for (ll i = 2; i < maxn; i++)
57         inv[i] = inv[i - 1] * inv[i] % mod;
58 }
59 ll C(ll x, ll y)
60 {
61     if (y > x)
62         return 0;
63     if (y == 0 || x == 0)
64         return 1;
65     return fac[x] * inv[y] % mod * inv[x - y] % mod;
66 }
67 int main(int argc, char const *argv[])
68 {
69     ios::sync_with_stdio(false);
70     cin.tie(0);
71     cout.tie(0);
72     int t;
73     init();
74     cin >> t;
75     while (t--)
76     {
77         cin >> n >> m >> k;
78         ll ans = 0;
79         if (k == 0)
80             ans = 1;
81         else if ((n - 1) * m < k)
82             ans = 0;
83         else
84         {
85             int c = min(k / n, m);
86             for (int i = 0; i <= c; i++)
87             {
88                 if (i % 2 == 0)
89                     ans = (ans + C(m, i) * C(k - i * n + m - 1, m - 1) % mod) % mod;
90                 else
91                     ans = (ans - C(m, i) * C(k - i * n + m - 1, m - 1) % mod + mod) % mod;
92             }
93         }
94         cout << ans << '\n';
95     }
96     return 0;
97 }
View Code

 

posted @ 2019-08-03 10:24  mool  阅读(261)  评论(0编辑  收藏  举报