Description
Input
一行由空格隔开的两个整数,分别是 n 和 m。
Output
一行表示答案。
Sample Input
Input1:
6 1
Input2:
6 3
Sample Output
Output1:
10
Output2:
2248
Data Constraint
Hint
第一个样例中,合法的方案有 (1, 1),(1, 2),(1, 3),(1, 6),(2, 1),(2, 2),(2, 3),(3, 1),(3, 2),(6, 1) 共 10 种。
思路
令F(x)=∏(1<=i<=2m)xi,
令F(x’)=∏(1<=i<=2m)n/xi,、
如果F(x)< n^m,则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=最后答案
因为s1=s3,s1+s2+s3=(n因数个数)^2m 所以只用求出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]
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=998244353;
int n,m;
long long s=1,ans=0,f[277][6777];
long long power(long long a,long long b)
{
int x=1,t=b;
while(t)
{
if(t&1) x=(x*a)%mod;
t>>=1; a=(a*a)%mod;
}
return x;
}
int main()
{
freopen("count.in","r",stdin); freopen("count.out","w",stdout);
scanf("%d%d",&n,&m);
if(n==1)
{
printf("1"); return 0;
}
for(int i=1; i*i<=n; i++) if(n%i==0)
{
if (n/i!=i) ans+=2; else ans++;
}
int t=n;
for(int x=2; x<=t; (x!=2&&x+2<=t)?x+=2:x++)
{
int w=0;
if(t%x==0)
{
while(t%x==0) w++,t/=x;
}else continue;
memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1; i<=2*m; i++)
{
for(int j=0; j<=w*m; j++)
{
for(int k=0; k<=min(w,j); k++) f[i][j]=(f[i][j]+f[i-1][j-k])%mod;
}
}
s=(s*f[2*m][w*m])%mod;
}
printf("%lld",((power(ans,2*m)%mod-s+mod)%mod*power(2,mod-2)%mod+s)%mod);
}