标签:inline eset amp ++ radius math 输入输出格式 lld ace
给定一个整数 n,求将 n 分解为互不相同的不小于 2 的数的乘积的方案数。答案模 998244353。
输入格式:
第一行一个整数 T,表示数据组数。
接下来 T 行,每行一个整数 n,意义如描述所述。
输出格式:
一共 TT 行,每行一个整数,表示答案。
样例中,因为
688=2×4×86=2×8×43=2×344=4×172=8×86=16×43
所以答案为 66
对于 10% 的数据,保证 n 为质数
对于 20% 的数据,保证 2≤n≤104
对于 50% 的数据,保证 2≤n≤107
对于 100% 的数据, 保证 2≤n≤1012
所有数据满足 1≤T≤5
题目链接:https://www.luogu.org/problemnew/show/P3861
吐槽一下:
调了两小时的dp[吐血].
解题报告:
没有,下一个[吐血].
AC代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#define FOR(i,s,t) for(register ll i=s;i<=t;++i)
#define ll long long
using namespace std;
const ll MOD=998244353;
ll T;
ll cnt,pos,ans,q;
ll n,tmp;
ll a[1333333];
int pos1[1000011],pos2[1000011];
ll f[8111][8111];
inline void divide(){
cnt=0;
q=sqrt(n);
for(register ll i=1;i*i<=n;++i)
if(n%(i*1ll)==0){
a[++cnt]=i,a[++cnt]=n*1ll/i;
if(1ll*i*i==n)--cnt;
}
stable_sort(a+1,a+cnt+1);
}
inline void dp(){
FOR(i,0,cnt)
FOR(j,0,cnt)
f[i][j]=0;
FOR(i,1,cnt){
++f[i][i];//printf("%lld\n",a[i],i);
a[i]<=q?pos1[a[i]]=i:pos2[(int)(n*1ll/a[i])]=i;
}
FOR(i,1,cnt)
FOR(j,1,cnt){
f[i][j]=(f[i][j]+f[i][j-1])%MOD;
if(i<=j)continue;
if(a[i]%a[j]==0){
tmp=a[i]/a[j];
tmp<=q?f[i][j]+=f[pos1[tmp]][j-1]:f[i][j]+=f[pos2[(int)(n*1ll/tmp)]][j-1];
f[i][j]%=MOD;
}
}
printf("%lld\n",f[cnt][cnt]-1);
}
int main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
divide();
dp();
}
return 0;
}
标签:inline eset amp ++ radius math 输入输出格式 lld ace
原文地址:http://www.cnblogs.com/Stump/p/7784886.html