• [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 ll  mxn=1e4+5,mod=1e9+7;
    ll  k,t,ans=1,dp[63][mxn];
    ll n;
    
    inline ll  read() {
    	char c=getchar(); ll  x=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 ll  chkmax(ll  &x,ll  y) {if(x<y) x=y;}
    inline ll  chkmin(ll  &x,ll  y) {if(x>y) x=y;}
    
    ll  qpow(ll  a,ll  b) 
    {
    	ll  res=1,bs=a;
    	while(b) {
    		if(b&1) res=1ll*res*bs%mod;
    		bs=1ll*bs*bs%mod;
    		b>>=1;
    	}
    	return res;
    }
    
    ll  inv(ll  x) {return qpow(x,mod-2);}
    
    ll  solve(ll  a,ll  cnt,ll  opt) 
    {
    	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];
    	}
    	ll  res=0;
    	for(ll  d=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);
    }
    
    int  main()
    {
    	scanf("%lld",&n); k=read();
    	for(ll  i=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;
    }
    
    
  • 相关阅读:
    C++——并发编程
    Poco C++——JSON解析
    #转载#我给所有新手程序员的建议
    #笔记# 如何阅读技术类书籍
    笔记:CSS hack的学习与了解…
    【笔记】CSS选择器整理(IE低版本支持性测试)
    呼吸灯效果
    ajax跨域问题-----jsonp
    【转】js里的时间函数集
    grunt与requirejs结合使用
  • 原文地址:https://www.cnblogs.com/list1/p/10516002.html
Copyright © 2020-2023  润新知