CF1097D Makoto and a Blackboard
Description:
給定\(n,k\) ,一共會進行\(k\) 次操作,每次操作會把\(n\) 等概率的變成\(n\) 的某個約數
求操作\(k\) 次後\(n\)的期望是多少,答案對
\(10^9+7\)
取模
Hint:
\(n \le 10^{15} ,k \le 10^4\)
Solution:
學到新姿勢了
考慮裸暴力dp
\(dp[i][k]=\sum_{j|i}dp[j][k-1]*\frac{1}{cnt}\)
顯然T飛
我們發現答案滿足積性
考慮把dp[i]拆成\(dp[p_0^{a_0}]*dp[p_1^{a_1}]*dp[p_2^{a_2}]\) 其中\(p_i\) 為質數
這樣狀態數會大大減少,複雜度\(O(k*log^2n)\)
暴力記搜就行
#include <map> #include <set> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define ls p<<1 #define rs p<<1|1 using namespace std; typedef long long ll; const llmxn=1e4+5,mod=1e9+7; llk,t,ans=1,dp[63][mxn]; ll n; inline llread() { char c=getchar(); llx=0,f=1; while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();} while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();} return x*f; } inline llchkmax(ll&x,lly) {if(x<y) x=y;} inline llchkmin(ll&x,lly) {if(x>y) x=y;} llqpow(lla,llb) { llres=1,bs=a; while(b) { if(b&1) res=1ll*res*bs%mod; bs=1ll*bs*bs%mod; b>>=1; } return res; } llinv(llx) {return qpow(x,mod-2);} llsolve(lla,llcnt,llopt) { if(cnt==0) { dp[cnt][opt]=1; return 1; } if(opt==0) { if(!dp[cnt][opt]) dp[cnt][opt]=1ll*solve(a,cnt-1,opt)*a%mod; return dp[cnt][opt]; } llres=0; for(lld=0;d<=cnt;++d) { if(!dp[d][opt-1]) dp[d][opt-1]=solve(a,d,opt-1); res=(res+dp[d][opt-1])%mod; } return (ll) (1ll*res*inv(cnt+1)%mod); } intmain() { scanf("%lld",&n); k=read(); for(lli=2;i*i<=n;++i) { if(n%i!=0) continue ; t=0; while(n%i==0) ++t,n/=i; memset(dp,0,sizeof(dp)); ans=1ll*ans*solve(i,t,k)%mod; } memset(dp,0,sizeof(dp)); if(n>1) ans=1ll*ans*solve(n,1,k)%mod; printf("%lld",ans); return 0; }