题解
- 令F(x)=∏(1<=i<=2m)xi,如果F(x)<n^m
- 令F(x')=∏(1<=i<=2m)n/xi,则F(x')>n^m
- 因为,F(x)*F(x')==n^2m,F(x)<n^m,所以F(x')>n^m
- 那么发现一个F(x)一定只对应一个F(x')
- 设F(x)<n^m有s1个,F(X)=n^m有s2个,F(X)>n^m有s3个
- 那么s1+s2+s3=为最后答案,那么s1=s3,所以只用求出s2的个数就好了
- 就转换为求F(X)=n^m的个数
- 现将n分解质因数n=p1^c1+p2^c2+...pk^ck
- n^m分解质因数就是p1^(c1*m)+p2^(c2*m)+...pk^(ck*m)
- 考虑就出对于每一个质因数的选数方案,再将它们乘起来就是所有的方案数了
- 考虑用dp求出选的方案数,设f[i][j]为选了i个数,sum是j的方案数
- f[i][j]=f[i][j]+f[i-1][j-k]
- j为枚举的当前的sum值0<=j<=ci*m
- k为枚举的转移的值0<=k<=min(ci,j)
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <algorithm>
4 #include <cstring>
5 #include <cmath>
6 using namespace std;
7 long long s2,f[210][210*100],mo=998244353,tot;
8 int n,m,k,num;
9 long long ksm(long long a,int b)
10 {
11 long long r=1;
12 for(;b;b>>=1,a=a*a%mo) if(b&1) r=r*a%mo;
13 return r;
14 }
15 void dp(int x)
16 {
17 memset(f,0,sizeof(f)); f[0][0]=1;
18 num=0; while (k%x==0) num++,k=k/x;
19 for (int i=1;i<=m*2;i++)
20 for (int j=0;j<=num*m;j++)
21 for (int z=0;z<=min(j,num);z++)
22 f[i][j]=(f[i][j]+f[i-1][j-z])%mo;
23 s2=(s2*f[m*2][num*m])%mo;
24 }
25 int main()
26 {
27 freopen("count.in","r",stdin);
28 freopen("count.out","w",stdout);
29 scanf("%d%d",&n,&m);
30 k=n; s2=1;
31 for (int i=1;i<=sqrt(n);i++)
32 if (n%i==0)
33 {
34 tot++;
35 if (i*i<n) tot++;
36 if (i>1&&k%i==0) dp(i);
37 }
38 if (k>1) dp(k);
39 printf("%lld",(ksm(tot,2*m)+s2)%mo*ksm(2,mo-2)%mo);
40 return 0;
41 }