专栏文章
题解:AT_abc425_e [ABC425E] Count Sequences 2
AT_abc425_e题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minr9ntv
- 此快照首次捕获于
- 2025/12/02 07:03 3 个月前
- 此快照最后确认于
- 2025/12/02 07:03 3 个月前
题目即求可重集排列方案数,我们知道答案为
证明是考虑其中分子为不考虑重复数的排列数,分母为相同数字的排列数。
但是我们知道模意义下除法需要逆元,而 在模 意义下有逆元当且仅当 ,但是题目的 是现场给定的,显然不能保证该性质。注意到 非常小,我们考虑对每个数进行质因数分解,计算每个质数在答案中的指数即可,这样除法就转化为了指数的减法。我们预处理每个数的质因数分解,计算阶乘时暴力枚举每个质因数,时间复杂度为 ,其中 是不超过 的数的最大质因数数量,显然非常小,于是可以通过。
Code:
CPP#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 3e5 + 10, maxa = 5000;
int t, n, mod;
long long res;
int a[maxn], cnt[maxa + 10];
vector<pair<int, int> > d[maxa + 10];
int main(){
scanf("%d %d", &t, &mod);
for (int i = 2; i <= maxa; i++){
int now = i;
for (int j = 2; j * j <= i; j++){
if (!(now % j)){
int cnt = 0;
for (;!(now % j); now /= j, cnt++);
d[i].push_back(make_pair(j, cnt));
}
}
now > 1 && (d[i].push_back(make_pair(now, 1)), 1538);
}
while (t--){
scanf("%d", &n), a[n + 1] = 0, res = 1;
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]), a[n + 1] += a[i];
}
for (int i = 2; i <= a[n + 1]; i++){
for (auto x: d[i]){
cnt[x.first] += x.second;
}
}
for (int i = 1; i <= n; i++){
for (int j = 2; j <= a[i]; j++){
for (auto x: d[j]){
cnt[x.first] -= x.second;
}
}
}
for (int i = 2; i <= maxa; i++){
for (;cnt[i]; res = res * i % mod, cnt[i]--);
}
printf("%lld\n", res);
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...