链接:https://codeforces.com/contest/1097/problem/D
考虑一个暴力DP
表示到第i轮, 当前的数是
的个数
只有可能是
的因数,最多大概是
但是你会发现状态已经很大了,并且无法
转移,GG!
于是考虑优化状态
我们可以对于质因数分开考虑
我们算出每一个质因数期望是什么,最后乘起来就是答案了
于是对于每一个质因数简单DP
表示到第
轮,次数为
的概率是什么
转移就暴力枚举上一次的次数是什么来转移及㐓了
次数显然很小,
就已经远远超出了,因此直接估算为60
至于不同质因数,大概20就远远超出了
因此,每次DP暴力转移就好了
我的代码已经十分暴力了。。
如果想跑得更快,可以在转移的时候加点前缀和后缀和什么的
就可以去掉一重循环
但是并没有必要。。
CODE:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const LL N=10005;
LL n,k;
LL ans=1;
LL f[N][61];
LL sum[61];
LL inv[61];
void calc (LL xx,LL x)
{
f[0][x]=1;for (LL u=0;u<x;u++) f[0][u]=0;
for (LL u=1;u<=k;u++)
{
for (LL i=0;i<=x;i++)
{
f[u][i]=0;
for (LL j=i;j<=x;j++)
f[u][i]=(f[u][i]+f[u-1][j]*inv[j+1]%MOD)%MOD;
}
}
LL lalal=0,now=1;
for (LL i=0;i<=x;i++)
{
lalal=(lalal+now*f[k][i]%MOD)%MOD;
now=now*xx%MOD;
}
ans=ans*lalal%MOD;
}
int main()
{
inv[1]=1;for (LL u=2;u<=60;u++) inv[u]=(MOD-MOD/u)*inv[MOD%u]%MOD;
scanf("%lld%lld",&n,&k);
for (LL u=2;u*u<=n;u++)
{
LL i=0;
while (n%u==0) {n/=u;i++;}
if (i==0) continue;
calc(u,i);
}
if (n!=1) calc(n,1);
printf("%lld\n",ans);
return 0;
}