牛客多校第六场 C、Generation

Generation

时间限制:3秒 | 内存限制:256M

Oak is given N empty and non-repeatable sets which are numbered from 1 to N.

Now Oak is going to do N operations. In the i-th operation, he will insert an integer x between 1 and M to every set indexed between i and N.

Oak wonders how many different results he can make after the N operations. Two results are different if and only if there exists a set in one result different from the set with the same index in another result.

Please help Oak calculate the answer. As the answer can be extremely large, output it modulo 998244353.

输入描述:

The input starts with one line containing exactly one integer T which is the number of test cases. (1 ≤ T ≤ 20)

Each test case contains one line with two integers N and M indicating the number of sets and the range of integers. (1 ≤ N ≤ 1018, 1 ≤ M ≤ 1018, )

输出描述:

For each test case, output “Case #x: y” in one line (without quotes), where x is the test case number (starting from 1) and y is the number of different results modulo 998244353.

Solution

一种不会读题读不懂题猜不到get不到题意的蓝瘦……
辛苦了hrtt算了一下午,感谢bh为我讲题。。。
这是一道排列组合题。问题转化为在n个格子里面依次涂m种颜色,每一步都从当前的格子(i=1..n)涂到最后的格子。m,n<=1e18,但是min(m,n)<=1e6。
我们假设在最后一个格子里有i种颜色,i<=min(n,m),那么选涂的颜色共有C(m,i)种可能;
第一个格子里面一定有且仅有1种颜色,有C(i,1)=i种可能;
从第2到第n格,这n-1个格子里填涂i-1种颜色,且选择起笔的格子有i-1个,这些格子在n-1个位置上的各种各样的可能形成一个C(n-1,i-1)的组合,i-1种颜色形成A(i-1,i-1)的排列;
综上,所求答案
ans =

i = 1 m i n ( m , n ) C m i C i 1 C n 1 i 1 A i 1 i 1

=
i = 1 m i n ( m , n ) C m i i A n 1 i 1

=
i = 1 m i n ( m , n ) m ! i ! ( m i ) ! i ( n 1 ) ! ( n i ) !

=
i = 1 m i n ( m , n ) m ! ( i 1 ) ! ( m i ) ! ( n 1 ) ! ( n i ) !

直接for 10 6 算就得了

#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define ull unsigned long long
#define ui unsigned int
const int MX = 1000005;
const ll MOD = 998244353;
int T;
ll n, m, q, ans;
ll N, M;
ll fac[MX], inv[MX];

ll fun(ll a, ll k) {
    ll res = 1;
    while (k) {
        if (k & 1) res = res * a % MOD;
        a = a * a % MOD;
        k >>= 1;
    }
    return res;
}

int main() {
    //freopen("../in", "r", stdin);
    fac[0] = inv[0] = 1;
    for (int i = 1; i <= 1000000; ++i) fac[i] = fac[i - 1] * i % MOD;
    inv[1000000] = fun(fac[1000000], MOD - 2);
    for (int i = 999999; i > 0; --i) inv[i] = inv[i + 1] * (i + 1) % MOD;

    scanf("%d", &T);
    for (int I = 1; I <= T; ++I) {
        scanf("%lld%lld", &n, &m);
        N = 1;
        M = m % MOD;
        ans = 0;
        q = min(n, m);
        for (int i = 1; i <= q; ++i) {
            ans = (ans + M * N % MOD * inv[i-1] % MOD) % MOD;
            M = (m - i) % MOD * M % MOD;
            N = (n - i) % MOD * N % MOD;
        }
        printf("Case #%d: %lld\n", I, ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ACM2017/article/details/81414695