题目描述
给定一个整数 nnn,求将 nnn 分解为互不相同的不小于 222 的数的乘积的方案数。答案模 998244353998244353998244353。
输入输出格式
输入格式:第一行一个整数 TTT,表示数据组数。
接下来 TTT 行,每行一个整数 nnn,意义如描述所述。
输出格式:一共 TTT 行,每行一个整数,表示答案。
输入输出样例
1 688
6
说明
样例中,因为
688=2×4×86=2×8×43=2×344=4×172=8×86=16×43688 = 2 \times 4 \times 86= 2 \times 8 \times 43= 2 \times 344= 4 \times 172= 8 \times 86= 16 \times 43688=2×4×86=2×8×43=2×344=4×172=8×86=16×43
所以答案为 666
对于 10%10\%10% 的数据,保证 nnn 为质数
对于 20%20\%20% 的数据,保证 2≤n≤1042 \leq n \leq 10^42≤n≤104
对于 50%50\%50% 的数据,保证 2≤n≤107 2 \leq n \leq 10^72≤n≤107
对于 100%100\%100% 的数据, 保证 2≤n≤1012 2 \leq n \leq 10^{12}2≤n≤1012
所有数据满足 1≤T≤51 \leq T \leq 51≤T≤5
对于每一个N,我们先求出它的第iii小因子facifac_{i}faci, 然后记录下因子jjj所对应的位置posjpos_{j}posj。这里有一个小技巧:
+ififif j≤Nj \le \sqrt{N}j≤√N, 则令pos1j=posjpos1_{j}=pos_{j}pos1j=posj
+ififif j>Nj > \sqrt{N}j>√N, 则令pos2Nj=posjpos2_{\frac{N}{j}}=pos_{j}pos2jN=posj
这样就可以把空间压缩为O(N)O(\sqrt{N})O(√N)
然后令dpijdp_{ij}dpij为把facifac_{i}faci分解成若干个小于等于facjfac_{j}facj的数(包括111)的积的方案总数,则:
dpij=dpij−1dp_{ij}=dp_{i j-1}dpij=dpij−1
ififif i=ji=ji=j, dpij++dp_{ij}++dpij++
ififif faci≡0,mod(facj)fac_{i} \equiv 0,mod( fac_{j})faci≡0,mod(facj), dpij+=dpposfacifacjj−1dp_{ij}+=dp_{pos_{\frac{fac{i}}{fac_{j}}} j-1}dpij+=dpposfacjfacij−1
#include<iostream>
#include<cstring>
#include<map>
#include<cmath>
#include<algorithm>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const long long MOD=998244353,MAXN=11000;
long long n,fac[MAXN],q;
int f[MAXN][MAXN],pos1[1000011],pos2[1000010],num;
map<long long,int> ans;
int main()
{
ios::sync_with_stdio(false);
int T,i,j;
cin>>T;
while(T--){
num=0;
cin>>n;
if(ans[n]){
cout<<ans[n]<<endl;
continue;
}
q=sqrt(n);
if(n%q==0){
fac[++num]=q;
if(q*q!=n){
fac[++num]=n/q;
}
}
f(i,1,q-1){
if(n%i==0){
fac[++num]=i;
fac[++num]=n/i;
}
}
f(i,1,num){
f(j,1,num){
f[i][j]=0;
}
}
sort(fac+1,fac+1+num);
f(i,1,num){
f[i][i]=1;
if(fac[i]<=q){
pos1[fac[i]]=i;
}
else{
pos2[n/fac[i]]=i;
}
}
f(i,1,num){
f(j,1,num){
f[i][j]+=f[i][j-1];
if(i<=j||fac[i]%fac[j]){
// cout<<i<<' '<<j<<' '<<f[i][j]<<endl;
continue;
}
long long tmp=fac[i]/fac[j];
if(tmp<=q){
f[i][j]+=f[pos1[tmp]][j-1];
}
else f[i][j]+=f[pos2[n/tmp]][j-1];
// cout<<i<<' '<<j<<' '<<f[i][j]<<endl;
f[i][j]%=MOD;
}
}
ans[n]=f[num][num]-1;
cout<<f[num][num]-1<<endl;
}
return 0;
}