听说灌水区大佬多,求条,玄关
  • 板块灌水区
  • 楼主KarmaticEnding
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/8/7 18:39
  • 上次更新2024/8/7 19:57:24
查看原帖
听说灌水区大佬多,求条,玄关
642173
KarmaticEnding楼主2024/8/7 18:39

学术区帖子传送门

原题传送门

如题

思路是分解 nn 的因数,记为 d1,d2,...d_1,d_2,...,然后记 fi,jf_{i,j} 表示将 did_i 分解成几个不大于 djd_j 的数的乘积的方案数。

有没有哪位大佬可以看看,为什么样例会输出1?

代码附上:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
int T;
long long n;
priority_queue<ll,vector<ll>,greater<ll> > q;
vector<ll> d;
ll f[6800][6800];
int pos1[1000010],pos2[1000010];
const long long mod=998244353;
void div(){
	for(ll i=1;i<=sqrt(n);++i){
		if(n%i==0){
			q.push(i);
			if(i*i==n){
				
			}
			else{
				q.push(n/i);
			}
		}
	}
	while(q.size()){
		d.push_back(q.top());//保证了d里面的数据从小到大排列
		q.pop();
	}
	for(int i=0;(i<<1)<=d.size();++i){
		pos1[d[i]]=i;//pos1[x]表示d[pos1[x]]=x
		pos2[d[i]]=d.size()-i-1;//pos2[x]表示d[pos2[x]]=n/x 这样做是为了减空间复杂度
	}
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%lld",&n);
		div();
		for(int i=0;i<d.size();++i){
			f[i][0]=(i==0);
			for(int j=1;j<d.size();++j){
				f[i][j]=f[i][j-1];//赋初值为d[i]分解不包含d[j]的方案数量
				if(j>i){
					break;
				}
				if(d[i]%d[j]==0){
					int pos,tmp=d[i]/d[j];
					if(tmp<=sqrt(n)){
						pos=pos1[tmp];
					}
					else{
						pos=pos2[n/tmp];
					}
					f[i][j]+=f[pos][j-1];
					f[i][j]%=mod;
				}
			}
		}
		printf("%lld\n",f[d.size()-1][d.size()-1]);
		d.clear();
	}
}
2024/8/7 18:39
加载中...