Codeforces Round #548 (Div. 2) D. Steps to One

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

题意:

给你一个空的序列,现在对其进行操作。

  1. [ 1 , m ] [1,m] [1,m]中随机取得一个数放到序列的最后。
  2. 如果整个序列的 g c d = 1 gcd=1 gcd=1退出。
  3. 否则进行第 1 1 1步。

求最后这个序列的期望长度。

首先根据期望的定义:
可以得到 l e n = ∑ i = 1 + ∞ i m i ⋅ R ( i ) len = \sum_{i=1}^{+\infty}\frac{i}{m^i}\cdot R(i) len=i=1+miiR(i)
R ( i ) R(i) R(i)表示当前序列长度为 i i i g c d = 1 gcd=1 gcd=1并且 i − 1 i-1 i1时的 g c d ≠ 1 gcd\neq 1 gcd̸=1的方案数。

假定当前序列长度为 i i i
不考虑 i − 1 i-1 i1时的影响时:
f ( i , n ) f(i,n) f(i,n)表示当前整个序列的 g c d = n gcd=n gcd=n的方案数。
g ( i , n ) g(i,n) g(i,n)表示当前整个序列的 g c d gcd gcd n n n的倍数的方案数。
显然: g ( i , n ) = ∑ n ∣ d f ( i , d ) g(i,n) = \sum_{n|d}f(i,d) g(i,n)=ndf(i,d) g ( i , n ) = ⌊ m n ⌋ i g(i,n) = \lfloor \frac{m}{n} \rfloor^i g(i,n)=nmi
莫比乌斯反演可以得到:
f ( i , n ) = ∑ n ∣ d g ( i , d ) ⋅ u ( d n ) f(i,n) = \sum_{n|d} g(i,d)\cdot u(\frac{d}{n}) f(i,n)=ndg(i,d)u(nd)
只需要知道 f ( i , 1 ) f(i,1) f(i,1)的值
f ( i , 1 ) = ∑ d = 1 m ⌊ m d ⌋ i ⋅ u ( d ) f(i,1) = \sum_{d=1}^{m}\lfloor \frac{m}{d} \rfloor^i\cdot u(d) f(i,1)=d=1mdmiu(d)
这时需要计算 i − 1 i-1 i1的影响:

由上述定义: R ( i ) = f ( i , 1 ) − m ⋅ f ( i − 1 , 1 ) R(i) = f(i,1) - m\cdot f(i-1,1) R(i)=f(i,1)mf(i1,1)
注意: R ( 1 ) = 1 R(1) = 1 R(1)=1
i > 1 i>1 i>1时满足上述式子。

带入:
l e n = 1 m + ∑ i = 2 + ∞ i m i ∑ d = 1 m ( ⌊ m d ⌋ i ⋅ u ( d ) − ⌊ m d ⌋ i − 1 ⋅ u ( d ) ⋅ m ) len = \frac{1}{m}+ \sum_{i=2}^{+\infty}\frac{i}{m^i}\sum_{d=1}^{m}(\lfloor \frac{m}{d} \rfloor^i\cdot u(d) - \lfloor \frac{m}{d} \rfloor^{i-1}\cdot u(d)\cdot m) len=m1+i=2+miid=1m(dmiu(d)dmi1u(d)m)
化简:
l e n = 1 m + ∑ i = 2 + ∞ i m i ∑ d = 1 m u ( d ) ⋅ ⌊ m d ⌋ i − 1 ⋅ ( ⌊ m d ⌋ − m ) len = \frac{1}{m}+\sum_{i=2}^{+\infty}\frac{i}{m^i}\sum_{d=1}^{m}u(d)\cdot\lfloor \frac{m}{d} \rfloor^{i-1} \cdot(\lfloor\frac{m}{d}\rfloor-m) len=m1+i=2+miid=1mu(d)dmi1(dmm)
交换求和顺序
l e n = 1 m + ∑ d = 1 m ( ⌊ m d ⌋ − m ) ⋅ u ( d ) ∑ i = 2 + ∞ i m i ⋅ ⌊ m d ⌋ i − 1 len =\frac{1}{m}+ \sum_{d=1}^{m}(\lfloor\frac{m}{d}\rfloor-m)\cdot u(d) \sum_{i=2}^{+\infty} \frac{i}{m^i}\cdot\lfloor \frac{m}{d} \rfloor^{i-1} len=m1+d=1m(dmm)u(d)i=2+miidmi1

q = 1 m ⋅ ⌊ m d ⌋ q = \frac{1}{m}\cdot\lfloor\frac{m}{d}\rfloor q=m1dm
H ( n ) = ∑ i = 2 q i − 1 ⋅ i H(n) =\sum_{i=2}q^{i-1}\cdot i H(n)=i=2qi1i
H ( n ) H(n) H(n) 错位相消:
得到:
( 1 − q ) ⋅ H ( n ) = q + q ⋅ ( 1 − q n ) 1 − q (1-q)\cdot H(n) = q+\frac{q\cdot (1-q^n)}{1-q} (1q)H(n)=q+1qq(1qn)
n = + ∞ n = +\infty n=+ ( 1 − q ) ⋅ H ( n ) = q + q 1 − q (1-q)\cdot H(n) = q+\frac{q}{1-q} (1q)H(n)=q+1qq
H ( n ) = q ⋅ ( 2 − q ) ( 1 − q ) 2 H (n) = \frac{q\cdot(2-q)}{(1-q)^2} H(n)=(1q)2q(2q)

l e n = 1 m + ∑ d = 1 m ( ⌊ m d ⌋ − m ) ⋅ u ( d ) ⋅ q ⋅ ( 2 − q ) m ⋅ ( 1 − q ) 2 len = \frac{1}{m}+ \sum_{d=1}^{m}(\lfloor\frac{m}{d}\rfloor-m)\cdot u(d) \cdot \frac{q\cdot(2-q)}{m\cdot (1-q)^2} len=m1+d=1m(dmm)u(d)m(1q)2q(2q)

这样就可以在 O ( m l o g m ) O(mlogm) O(mlogm)时间内解决。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e18
const int maxn = 4e5+100;
const int mod = 1e9+7;
typedef long long ll;

ll powmod(ll x,ll n) {
    ll ret=1;
    for(;n>0;n>>=1,x=x*x%mod) if(n&1) ret=ret*x%mod;
    return ret;
}
int u[maxn],isp[maxn],tab[maxn];
void init(int n) {
    u[1] = 1;int top =0 ;
    for(int i=2;i<=n;++i) {
        if(!isp[i])tab[top++] = i,u[i]=-1;
        for(int j=0;j<top&&tab[j]*i<=n;++j){
            isp[i*tab[j]] = 1;
            if(i%tab[j]==0) {
                u[i*tab[j]] = 0;
                break;
            }
            u[i*tab[j]] = -u[i];
        }
    }
}
ll cal(ll n,ll d) {
    ll q = n/d*powmod(n,mod-2)%mod;
    ll b = powmod(1-q,mod-2);
    ll ans = q*(2-q)%mod*b%mod*b%mod;
    return (ans + mod)%mod;
}
ll slove(ll n) {
    ll ans = powmod(n,mod-2);
    for(int i=2;i<=n;++i) {
        ans = ans + 1ll*u[i]*((n/i-n)*powmod(n,mod-2)%mod*cal(n,i)%mod);
        ans %= mod;
    }
    return (ans + mod)%mod;
}
int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    int n,k,cnt=0;
    init(2e5);
    cnt = 0;
    cin>>n;
    cout<<slove(n)<<'\n';
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值