码迷,mamicode.com
首页 > 编程语言 > 详细

Hello 2019 D 素因子贡献法计算期望 + 概率dp + 滚动数组

时间:2019-05-03 19:59:03      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:hello   bit   一个   题解   line   操作   定义   cin   mat   

https://codeforces.com/contest/1097/problem/D

题意

给你一个n和k,问n经过k次操作之后留下的n的期望,每次操作n随机变成一个n的因数

题解

  • 概率dp计算出每个素因子留下的概率,乘以这个素因子的值就是这个素因子的贡献期望
  • 定义\(dp[i][j]\)为第i次操作后剩下j个素因子的概率,概率dp顺着推
    • \(dp[i][j]->dp[i+1][k](k<=j)\)
    • \(dp[i+1][k]+=dp[i][j]\frac{1}{j+1}(k<=j)\)
  • \(ans=\sum^{cnt}_{i=1}\sum^{num[i]}_{j=0}pr[i]^j*dp[k][j]\)
  • 二维滚动数组滚掉一维

代码

#include<bits/stdc++.h>
#define P 1000000007
#define M 32000000
#define MAXN 100
#define ll long long 
using namespace std;
ll dp[2][MAXN],inv[MAXN],n,ans=1;
int vi[M],sz,k,pr[M];
void sieve(){
    inv[0]=inv[1]=1;
    for(int i=2;i<MAXN;i++)inv[i]=(P-P/i)*inv[P%i]%P;

    for(ll i=2;i<M;i++){
        if(!vi[i])pr[++sz]=i;
        for(int j=1;j<=sz&&pr[j]*i<M;j++){
            vi[pr[j]*i]=1;
            if(i%pr[j]==0)break;
        }
    }
}

int main(){
    sieve();
    cin>>n>>k;
    for(int i=1;i<=sz&&pr[i]<=n;i++){
        int cnt=0;
        if(n%pr[i])continue;
        while(n%pr[i]==0){
            n/=pr[i];
            cnt++;
        }
        memset(dp,0,sizeof(dp));          //
        dp[0][cnt]=1;
        int st=0;
        for(int j=0;j<k;j++){
            memset(dp[st^1],0,sizeof(dp[st^1]));
            for(int p=0;p<=cnt;p++){
                for(int q=0;q<=p;q++){
                    dp[st^1][q]+=dp[st][p]*inv[p+1]%P;
                    dp[st^1][q]%=P;
                }
            }
            st^=1;
        }
        ll mul=1,tp=0;
        for(int j=0;j<=cnt;j++){
            tp+=dp[st][j]*mul%P;
            tp%=P;
            mul=mul*pr[i]%P;
        }
        ans=ans*tp%P;                //
    }
    if(n>1){
        memset(dp,0,sizeof(dp));
        dp[0][1]=1;
        int st=0;
        for(int j=0;j<k;j++){
            memset(dp[st^1],0,sizeof(dp[st^1]));
            for(int p=0;p<=1;p++){
                for(int q=0;q<=p;q++){
                    dp[st^1][q]+=dp[st][p]*inv[p+1]%P;
                    dp[st^1][q]%=P;
                }
            }
            st^=1;
        }
        ll mul=1,tp=0;
        for(int j=0;j<=1;j++){
            tp+=dp[st][j]*mul%P;
            tp%=P;
            mul=mul*n%P;
        }
        ans=ans*tp%P;
    }
    cout<<ans;
}

Hello 2019 D 素因子贡献法计算期望 + 概率dp + 滚动数组

标签:hello   bit   一个   题解   line   操作   定义   cin   mat   

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10806133.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!