• 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 << '
    ';
    95     }
    96     return 0;
    97 }
    View Code
  • 相关阅读:
    PPT能输英文不能输汉字
    常用HTML正则表达式
    Log4j使用总结
    JsonConfig过滤对象属性
    打开”我的电脑“,不显示”共享文档“和”我的文档“,解决办法。(windows XP系统)
    错误org.hibernate.LazyInitializationException
    Tomcat中实现IP访问限制
    windows server 2008中让AD域中的普通用户可以 远程登录 域控服务器。
    ibatis简介及 like查询
    IE访问页面的时候,受限制的解决方案。
  • 原文地址:https://www.cnblogs.com/mooleetzi/p/11293952.html
Copyright © 2020-2023  润新知