【CodeForces - 1139D】Steps to One(期望dp,容斥)

Vivek initially has an empty array a and some integer constant m.

He performs the following algorithm:

1.Select a random integer x uniformly in range from 1 to m and append it to the end of a.
Compute the greatest common divisor of integers in a.
2.In case it equals to 1, break
3.Otherwise, return to step 1.
Find the expected length of a. It can be shown that it can be represented as P/Q where P and Q are coprime integers and Q≠0(mod109+7). Print the value of P ⋅ Q − 1 ( m o d 1 0 9 + 7 ) . P⋅Q−1(mod10^9+7). PQ1(mod109+7).

Input
The first and only line contains a single integer m (1≤m≤100000).

Output
Print a single integer — the expected length of the array a written as P⋅Q−1(mod109+7).

Examples
Input
1
Output
1
Input
2
Output
2
Input
4
Output
333333338

为了ac这题昨天我恶补了期望的知识了。
这里就类似用到期望的可加的性质,直观上去做感觉就涉及到了无穷级数了。然后在求这类期望时,有点用到了动态规划里的状态这个东西,然后建立递推式。
这里我们设 f ( x ) f(x) f(x)为当前的 g c d gcd gcd已经是 x x x了,然后在这个基础上,我们要使其 g c d gcd gcd到大 1 1 1时的步数的期望。
则有: f ( x ) = 1 + ∑ i = 1 m f ( g c d ( x , i ) ) m f(x)=1+\sum_{i=1}^m\frac{f(gcd(x,i))}{m} f(x)=1+i=1mmf(gcd(x,i))

其实我觉得,这个递推式子不想传统的状态转移,因为这里造成的结果是自己有转移到自己了,更像是列方程求未知数一样。然后,我们把右边状态为x的项移到左边,就想状态转移方程了。

这里很显然要去枚举x的因子了。
f ( x ) = 1 + ∑ d ∣ x f ( d ) ∗ ∑ d ∣ j g c d ( j , x ) = = d m f(x)=1+\sum_{d|x}\frac{f(d)*\sum_{d|j}gcd(j,x)==d}{m} f(x)=1+dxmf(d)djgcd(j,x)==d

显然第二个和式用容斥来做,简答推导一下
m f ( x ) = m + ∑ d ∣ x f ( d ) ∗ ∑ d ∣ j g c d ( j d , x d ) = = 1 mf(x)=m+\sum_{d|x}f(d)*\sum_{d|j}gcd(\frac{j}{d},\frac{x}{d})==1 mf(x)=m+dxf(d)djgcd(dj,dx)==1
m f ( x ) = m + ∑ d ∣ x f ( d ) ∗ ∑ p = 1 ⌊ m d ⌋ g c d ( p , x d ) = = 1 mf(x)=m+\sum_{d|x}f(d)* \sum_{p=1}^{\lfloor \frac{m}{d}\rfloor}gcd(p,\frac{x}{d})==1 mf(x)=m+dxf(d)p=1dmgcd(p,dx)==1
然后把x移到左边
( m − ⌊ m x ⌋ ) f ( x ) = m + ∑ d ∣ x 且 d 不 等 于 x f ( d ) ∗ ∑ p = 1 ⌊ m d ⌋ g c d ( p , x d ) = = 1 (m-\lfloor\frac{m}{x}\rfloor)f(x)=m+\sum_{d|x且d不等于x}f(d)* \sum_{p=1}^{\lfloor \frac{m}{d}\rfloor}gcd(p,\frac{x}{d})==1 (mxm)f(x)=m+dxdxf(d)p=1dmgcd(p,dx)==1

然后就可以做了
代码:

#include
#include
#include
#include
#include
#include
#define INF 0x7f7f7f7f
#define maxx 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
int pr[maxx],cnt;
int P[maxx];
int m;
void init()
{
    P[1]=1;
    for(int i=2;i<maxx;i++)
    {
        if(!P[i])
        {
            P[i]=i;
            pr[++cnt]=i;
        }
        for(int j=1;j<=cnt&&pr[j]<=P[i];j++)
        {
            if((ll)pr[j]*i>=maxx)break;
            P[pr[j]*i]=pr[j];
        }
    }
}

int _fac[15],_tot;
void _getFac(int x)
{
    _tot=0;
    while(x!=1)
    {
        int now=P[x];
        _fac[_tot++]=now;
        while(x%now==0)x/=now;
    }
}
int getNum(int total,int x)
{
    _getFac(x);
    int ans=0;
    for(int s=0;s<(1<<_tot);s++)
    {
        int temp=1;
        int num=0;
        for(int i=0;i<_tot;i++)
        {
            if((s>>i)&1)
            {
                num++;
                temp*=_fac[i];
            }
        }
        if(num&1)ans-=total/temp;
        else ans+=total/temp;
    }
    return ans;
}

int fac[15],tot;
int e[15];
void getFac(int x)
{
    tot=0;
    while(x!=1)
    {
        int now=P[x];
        fac[tot]=now;
        e[tot]=0;
        while(x%now==0)
        {
            x/=now;
            e[tot]++;
        }
        tot++;
    }
}
int f[maxx];
int res;
void dfs(int x,int cur,int d)
{
    if(cur==tot)
    {
        if(d!=x)
        {
            res+=(ll)f[d]*getNum(m/d,x/d)%mod;
            if(res>=mod)res-=mod;
        }
        return;
    }
    dfs(x,cur+1,d);
    int now=d;
    for(int i=1;i<=e[cur];i++)
    {
        now*=fac[cur];
        dfs(x,cur+1,now);
    }
}
int _p(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=(ll)ans*a%mod;
        a=(ll)a*a%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
    init();
    cin>>m;
    f[1]=0;
    int ans=0;
    for(int i=2;i<=m;i++)
    {
        res=m;
        getFac(i);
        dfs(i,0,1);
        f[i]=(ll)res*_p(m-m/i,mod-2)%mod;

        ans+=f[i];
        if(ans>=mod)ans-=mod;
    }
    cout<<(1+(ll)ans*_p(m,mod-2)%mod)%mod<<endl;
    return 0;
}

你可能感兴趣的:(容斥原理,概率与期望)