D. Counting Factorizations (dp 组合数学)
链接:https://codeforces.com/contest/1794/problem/D
题意:给定2n个数,要求选n个互不相同的素数作质因数分解的底数,剩余n个数作指数,问能表示多少不同的数。
n<=2022 a[i]<=1e6
题解:容易想到选完素数后,答案是多重组合n!/(r1!r2!r3!...),其中ri表示某个数的个数,注意到显然当素数个数<n时为0,故我们只考虑素数个数>=n的情况。
对于所有非素数,显然其ri不会变化,对于素数,其值为ri(未被选择)或ri-1(被选择),故答案的一部分n!/(r1!...rk!)不变(非素数部分),对于变化的部分,1/(ri!...rj!)(素数部分)的所有和可以用dp做(只有-1和-0两种情况,可转移),令f(i,j)表示前i个素数中j个数被选的所有可能和,f(i,j)=f(i-1,j)1/ri!+f(i-1,j-1)1/(ri-1)!,预处理阶乘和阶乘的逆元即可O(n2)得到答案。
代码:
#define int long long
using namespace std;
const int N=5010,mod=998244353,M=1e6+100;
int w[N],c[N],a[N],p[M],fac[M],f[N][N],v[M],cnt[M],inv[M];
int qpow(int x,int y){
int ans=1;
while(y){
if(y&1) ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans;
}
int m;
bool primes(int x){
if(x==1) return false;
for(int i=2;i*i<=x;i++){
if(x%i==0) return false;
}
return true;
}
int invv(int x){
return qpow(x,mod-2);
}
void init(){
fac[0]=1;
for(int i=1;i<=1e6+10;i++){
fac[i]=fac[i-1]*i%mod;
}
inv[0]=1;
inv[1]=1;
for(int i=2;i<=1e6+10;i++){
inv[i]=invv(fac[i]);
}
}
signed main(){
init();
int n;cin>>n;
int k=0,t=0;
for(int i=1;i<=n+n;i++) cin>>a[i];
// sort(a+1,a+n+n+1);
for(int i=1;i<=n+n;i++){
if(!primes(a[i])){
cnt[a[i]]++;
if(cnt[a[i]]==1){
w[++k]=a[i];
}
}
else{
cnt[a[i]]++;
if(cnt[a[i]]==1)
c[++t]=a[i];
}
}
if(t<n){
cout<<0;
return 0;
}
int res=fac[n];
for(int i=1;i<=k;i++){
res=res*inv[cnt[w[i]]]%mod;
}
f[0][0]=1;
for(int i=1;i<=t;i++){
f[i][0]=f[i-1][0]*inv[cnt[c[i]]]%mod;
for(int j=1;j<=min(n,i);j++){
f[i][j]=(f[i-1][j]*inv[cnt[c[i]]]%mod+f[i-1][j-1]*inv[cnt[c[i]]-1]%mod)%mod;
}
}
res=res*f[t][n]%mod;
cout<<res;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App