牛客多校第六场 C、Generation

本文介绍了一个复杂的排列组合问题,该问题涉及在一系列空集中插入特定范围内的整数,并探讨了如何通过数学公式来计算不同结果的数量。最终,提供了一个高效的算法实现方案,用于解决大规模数据集下的计算挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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=1min(m,n)CimC1iCi1n1Ai1i1∑i=1min(m,n)Cmi∗Ci1∗Cn−1i−1∗Ai−1i−1

=
i=1min(m,n)CimiAi1n1∑i=1min(m,n)Cmi∗i∗An−1i−1

=
i=1min(m,n)m!i!(mi)!i(n1)!(ni)!∑i=1min(m,n)m!i!(m−i)!∗i∗(n−1)!(n−i)!

=
i=1min(m,n)m!(i1)!(mi)!(n1)!(ni)!∑i=1min(m,n)m!(i−1)!(m−i)!∗(n−1)!(n−i)!

直接for106106算就得了
#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值