G - Shinyruo and KFC Gym - 103428G
题意
给你n种不同的食物,每种食物有 a i a_i ai多个,食物个数不超过1e5,现在一共有m个人, 1 ≤ k ≤ m 1 \le k \le m 1≤k≤m ,每种食物最多拿一个,每个人可以拿多种食物,输出食物分配方案。
思路
关键语句,食物个数不超过1e5,说明给你的数据会有很多重复的样例,对于每个重复的样例我们可以采用快速幂这样累加答案,而且去重过后的数组长度不会太大,所以完全可以写暴力。枚举人数来写。
代码
在这里插#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long
using namespace std;
const int N = 1e5 + 100, mod = 998244353;
int arr[N], sum[N], fac[N], infac[N];
int ksm(int a, int b)//快速幂
{
int ans = 1;
while (b)
{
if (b & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ans;
}
int C(int n, int m)//组合数公式
{
if (m < 0 || n < m) return 0;
return fac[n] * infac[m] % mod * infac[n - m] % mod;
}
void init()//预处理阶乘,逆元
{
fac[0] = 1;
for (int i = 1; i <= N - 1; i++) fac[i] = (fac[i - 1] * i) % mod;
for (int i = 0; i <= N - 1; i++) infac[i] = ksm(fac[i], mod - 2);
}
signed main()
{
IOS;
init();
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> arr[i], sum[arr[i]]++;
sort(arr + 1, arr + 1 + n);//排序不影响结果,每个数都会算到的
int r = unique(arr + 1, arr + 1 + n) - arr - 1;//去重,也可以选用map
int l = 1;
while (arr[l] == 0) l++;//找到第一个不为0的数,题目说了
for (int i = 1; i <= m; i++)
{
int ans = 1;
for (int j = l; j <= r; j++) ans = (ans * ksm( C(i, arr[j]), sum[arr[j]]) ) % mod;
cout << ans % mod << endl;
}
return 0;
}入代码片