题解-CF1139D Steps to One

题面

CF1139D Steps to One

一个数列,每次随机选一个 ([1,m]) 之间的数加在数列末尾,数列中所有数的 (gcd=1) 时停止,求期望长度 (mod 10^9+7)

数据范围:(1le mle 10^5)


蒟蒻语

这题的非 dp 做法讲得太玄了而且写题解的人貌似不屑于解释/yiw,于是蒟蒻来写一篇。

(其实是 ubuntu 剪贴板炸了没得记录题目了只好写题解了/wul)。


蒟蒻解

先推一波概率期望式((E(x))(x) 的期望,(P(x))(x) 事件的概率)。

[egin{split} E(len)=&sum_{ige 1}P(len=i)cdot i\ =&sum_{ige 1}P(len=i)sum_{j=1}^i\ =&sum_{jge 1}sum_{ige j}P(len=i)\ =&sum_{ige 1}P(lenge i)\ =&1+sum_{ige 1}P(len>i)\ end{split} ]

因为 (gcd_{i=1}^{len} a_i=1) 就结束了,所以:

[egin{split} P(len>i)=&Pleft(left(gcd_{j=1}^{i} a_i ight)>1 ight)\ =&1-Pleft(left(gcd_{j=1}^{i} a_i ight)=1 ight)\ =&1-frac{sum_{a_1=1}^msum_{a_2=1}^mcdotssum_{a_i=1}^mepsilonleft(left(gcd_{j=1}^{i} a_i ight) ight)}{m^i}\ =&^{color{#aa88cc}{(1)}}1-frac{sum_{a_1=1}^msum_{a_2=1}^mcdotssum_{a_i=1}^msum_{d|left(gcd_{j=1}^{i} a_i ight)}mu(d)}{m^i}\ =&1-frac{sum_{d=1}^mmu(d)sum_{a_1=1}^m[d|a_1]sum_{a_2=1}^m[d|a_2]cdotssum_{a_i=1}^m[d|a_i]}{m^i}\ =&1-frac{sum_{d=1}^mmu(d)left(lfloorfrac{m}{d} floor ight)^i}{m^i}\ =&^{color{#eeaa22}{(2)}}-frac{sum_{d=2}^mmu(d)left(lfloorfrac{m}{d} floor ight)^i}{m^i}\ end{split} ]

(color{#aa88cc}{(1)}) 就是一个莫反,(color{#eeaa22}{(2)}) 就是把 (d=1) 的值和 (1) 抵消掉。

带回上式:

[egin{split} E(len)=&1+sum_{ige 1}P(len>i)\ =&1-sum_{ige 1}frac{sum_{d=2}^mmu(d)left(lfloorfrac{m}{d} floor ight)^i}{m^i}\ =&1-sum_{ige 1}frac{1}{m^i}sum_{d=2}^mmu(d)left(lfloorfrac{m}{d} floor ight)^i\ =&1-sum_{d=2}^mmu(d)sum_{ige 1}left(frac{lfloorfrac{m}{d} floor}{m} ight)^i\ =&^{color{#ff2211}{(3)}}1-sum_{d=2}^mmu(d)frac{lfloorfrac{m}{d} floor}{m-lfloorfrac{m}{d} floor}\ end{split} ]

(color{#ff2211}{(3)}) 是无穷等比数列求值:

[s=x+x^2+x^3+cdots\ sx=x^2+x^3+x^4+cdots\ s-sx=x\ s=frac{x}{1-x}\ ]

然后就可以筛个 (mu(i)) 就可以 (Theta(m)) 地算了,当然您可以杜教到 (Theta(m^{frac 23})),但是那么秀有什么意思呢……


代码

#include <bits/stdc++.h>
using namespace std;

//Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair((a),(b))
#define x first
#define y second
#define be(a) (a).begin()
#define en(a) (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define R(i,a,b) for(int i=(a),I=(b);i<I;i++)
#define L(i,a,b) for(int i=(a),I=(b);i>I;i--)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int mod=1e9+7;

//Sieve
struct sieve{
	int n;
	vector<bool> np;
	vector<int> prime,mu,inv;
	void Sieve(){
		np[1]=true,mu[1]=1;
		R(i,2,n){
			if(!np[i]) prime.pb(i),mu[i]=-1;
			for(int p:prime){
				if(!(i*p<n)) break;
				np[i*p]=true;
				if(i%p==0){mu[i*p]=0;break;}
				mu[i*p]=mu[i]*mu[p];
			}
		}
		inv[1]=1;
		R(i,2,n) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	}
	sieve(int _n){
		n=_n,np.assign(n,false),inv.resize(n);
		prime.clear(),mu.resize(n),Sieve();
	}
};

//Main
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int n; cin>>n;
	sieve math(n+1);
	int ans=1;
	R(i,2,n+1) (ans+=mod-1ll*(mod+math.mu[i])%mod
			   *(n/i)%mod*math.inv[n-n/i]%mod)%=mod;
	cout<<ans<<'
'; 
	return 0;
}

祝大家学习愉快!

原文地址:https://www.cnblogs.com/George1123/p/13586454.html