QOJ 5356 esperar

题目传送门

我们先把原式子转化一下,变为 \(\displaystyle\prod_{i=1}^{n} d_i\ge \prod_{i=1}^{n}\dfrac{b_i}{d_i}\),我们令 \(c_i=\dfrac{b_i}{d_i}\),则原式化简为 \(\displaystyle\prod_{i=1}^{n} d_i\ge \prod_{i=1}^{n}c_i\)

注意到当 \(d\)\(x\)\(\dfrac{b_i}{x}\) 是一种对称情况,所以 \(\displaystyle\prod_{i=1}^{n} d_i> \prod_{i=1}^{n}c_i\) 的方案数和 \(\displaystyle\prod_{i=1}^{n} d_i< \prod_{i=1}^{n}c_i\) 的方案数是一样的。

也就是说我们只需要算总方案数和 \(\displaystyle\prod_{i=1}^{n} d_i= \prod_{i=1}^{n}c_i\) 的方案数。

这个东西对于每个质因子是独立的,所以我们对于每个质因子 dp 一下即可。

具体地,假设当前处理质因子 \(p\),设 \(f_i\) 表示 \(\displaystyle\prod_{i=1}^{n} d_i\) 中的质因子 \(p\) 个数比 \(\displaystyle\prod_{i=1}^{n} c_i\) 中的质因子 \(p\) 个数多 \(i\) 个(\(i\) 可以是非正数)。

于是就做完了。

AC code:

#include<bits/stdc++.h>
#define int long long
#define N 105
#define M 6005
#define B 3000
#define pii pair<int,int>
#define x first
#define y second
#define mod 998244353
#define inf 1e9
using namespace std;
int T=1,n,a[N],f[M],g[M];
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)(res*=x)%=mod;
		(x*=x)%=mod;
		y>>=1;
	}
	return res;
}
void solve(int cs){
	cin>>n;
	set<int>s;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		int x=a[i];
		for(int j=2;j*j<=x;j++){
			if(x%j==0){
				s.insert(j);
				while(x%j==0)x/=j;
			}
		}
		if(x!=1)s.insert(x);
	}
	int res1=1,res2=1;
	for(auto it:s){
		memset(f,0,sizeof f);
		f[B]=1;
		for(int i=1;i<=n;i++){
			int x=a[i],cnt=0;
			if(x%it==0){
				memset(g,0,sizeof g);
				while(x%it==0){
					x/=it;
					cnt++;
				}
				for(int j=0;j<M;j++){
					if(!f[j])continue;
					for(int k=-cnt;k<=cnt;k++){
						(g[j+k]+=f[j]*((cnt-abs(k))/2+1))%=mod;
					}
				}
				memcpy(f,g,sizeof g);
			}
		}
		int sum=0;
		for(int i=0;i<M;i++){
			(sum+=f[i])%=mod;
		}
		(res1*=f[B])%=mod;
		(res2*=sum)%=mod;
	}
	cout<<(res2+res1)%mod*ksm(2,mod-2)%mod<<'\n';
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
//	cin>>T;
//	init();
	for(int cs=1;cs<=T;cs++){
		solve(cs);
	}
	return 0;
}
posted @ 2025-04-24 20:43  zxh923  阅读(19)  评论(0)    收藏  举报