HELLO 2019 - Makoto and a Blackboard (积性函数+DP期望)

Makoto and a Blackboard

题目链接: D - Makoto and a Blackboard

题意

给你一个N,定义一个操作:将N替换为他的一个因子(包括1和N)

现在重复K次以上操作,问最后期望的值是多少?

数据范围: N < = 1 0 15 , K < = 1 0 4 N <= 10^{15}, K <= 10^4 N<=1015,K<=104


思路

我的思路

求期望的有两种做法,

  1. DP存的是概率,直接是最后所有可能的结果乘以他们的概率,加起来
  2. DP存的是期望,利用公式 总 期 望 = 所 有 可 以 转 移 的 子 期 望 ∗ 他 们 发 生 的 概 率 总期望 = 所有可以转移的子期望*他们发生的概率 =

但其实这两种期望并不关键,最关键的发现积性函数这个性质

官方思路

How to solve the problem if n n n is a prime power p α p^α pα? We can simply use dynamic programming. Let D P i , j DP_{i,j} DPi,j denote the probability that after ii steps the current number on the blackboard is p j p^j pj. At the beginning, D P 0 , α = 1 DP_{0,α}=1 DP0,α=1. The transitions in DP are rather straightforward. The expected value of the number on the blackboard is then
∑ j = 0 α D P k , j p j \sum_{j=0}^{\alpha} DP_{k, j} p^j j=0αDPk,jpj

What if n n n is not a prime power? We can observe that the result is multiplicative on n n n. Therefore, we factorize n = p 1 α 1 p 2 α 2 … p ℓ α ℓ n=p_1^{α1}p_2^{α2}…p_ℓ^{αℓ} n=p1α1p2α2pα, apply the solution above for each prime power p 1 α 1 p_1^{α1} p1α1 through p ℓ α ℓ p_ℓ^{αℓ} pα, and eventually multiply the results.

Another problem is that we need to write a single integer modulo 1 0 9 + 7 10^9+7 109+7 even though the answer is a rational number. To cope with this, we notice that 1 0 9 + 7 10^9+7 109+7 is prime. Therefore, thanks to the Fermat Little Theorem, dividing by some number xx is equivalent to multiplying by x 1 0 9 + 5 x^{10^9+5} x109+5, modulo 1 0 9 + 7 10^9+7 109+7 . We use the quick exponentiation to compute the results.

The overall complexity is $ O(\sqrt{n}+k \cdot \log n)$

这里非常重要的就是积性函数,既 f ( 6 ) = f ( 2 ) ∗ f ( 3 ) , f ( 30 ) = f ( 5 ) ∗ f ( 2 ) ∗ f ( 3 ) f(6) = f(2)*f(3),f(30) = f(5)*f(2)*f(3) f(6)=f(2)f(3),f(30)=f(5)f(2)f(3)

关于积性函数链接:https://www.cnblogs.com/zhoushuyu/p/8275530.html


代码

#include
using namespace std;
#define rep(i,j,k) for(ll i = (ll)j;i <= (ll)k;i ++)
#define debug(x) cerr<<#x<<":"<
#define pb push_back

typedef long long ll;
const ll MAXN = 1e6+7;
const ll MOD = 1e9+7;

ll dp[10007][107]; //dp[i][j] : the possibility of after i times the j power now value

ll inv[107],n,k;

ll fpow(ll a,ll x) {
    ll res = 1;
    while (x) {
        if (x&1) res = res*a%MOD;
        a = a*a%MOD;
        x >>= 1;
    }
    return res;
}

ll solve (ll x,ll ci) {
    rep(i,0,k) rep(j,0,ci) dp[i][j] = 0;
    dp[0][ci] = 1;
    rep(i,1,k) {
        rep(j,0,ci) {
            rep(m,j,ci) {
                dp[i][j] = (dp[i][j] + dp[i-1][m]*(inv[m+1])%MOD)%MOD;
            }
        }
    }

    ll res = 0;
    rep(i,0,ci) {
        res = (res + fpow(x,i)*dp[k][i]%MOD)%MOD;
    }

    return res;
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    rep(i,1,100) inv[i] = fpow(i*1LL,MOD-2);

    cin >> n >> k;

    ll ans = 1;
    for (ll i = 2;i*i <= n;i ++) {
        if (n%i==0) {
            ll cnt = 0;
            while (n%i==0) n/=i,cnt++;
            ans = ans*solve(i,cnt)%MOD;
        }
    }
    if (n!=1) ans = ans*solve(n,1)%MOD;

    cout << ans << endl;
}

你可能感兴趣的:(DP,万物)