CF1139D Steps to One

很好的一道题。

最开始我想的是 \(dp\),但是在序列 \(gcd\) 不变的时候有点想不明白。

后来看了几位大佬的思路,终于会了。

CF1139D Steps to One

题目大意:

一个初始为空的数列,每次等概率随机在末尾放入一个 \(1\)\(m\) 之间的数,序列 \(gcd=1\) 时结束,问序列长度的期望。

题目思路:

如果你实在是不会什么方法,那就直接推式子,先将期望的定义写出来,之后一步步化简。

\(X\) 为步数:

(解释在后面)

式子:

\[\begin{align} E[X] &= \sum_jjP(X=j)\\ &= \sum_j\sum_i^j1P(X=j)\\ &= \sum_i\sum_{j\geq i}P(X=j)\\ &= \sum_iP(X\geq i)\\ &= 1+\sum_iP(X>i)\\ &= 1+\sum_i(1-P(\gcd_i(a_i)=1)) \\ &= 1+\sum_i\frac{m^i-\sum_{k\geq 1}\mu(k)\lfloor\frac{m}{k}\rfloor^i}{m^i}\\ &= 1+\sum_i\frac{m^i-m^i-\sum_{k\geq 2}\mu(k)\lfloor\frac{m}{k}\rfloor^i}{m^i}\\ &= 1-\sum_i\frac{\sum_{k\geq 2}\mu(k)\lfloor\frac{m}{k}\rfloor^i}{m^i}\\ &= 1-\sum_{k\geq 2}\mu(k)\sum_i\left(\frac{\lfloor\frac{m}{k}\rfloor}{m}\right)^i\\ &= 1-\sum_{k\geq 2}\mu(k)\frac{\lfloor\frac{m}{k}\rfloor}{m}\lim_{n\rightarrow \infty}\frac{1-(\frac{\lfloor\frac{m}{k}\rfloor}{m})^n}{1-\frac{\lfloor\frac{m}{k}\rfloor}{m}}\\ &= 1-\sum_{k\geq 2}\mu(k)\frac{\lfloor\frac{m}{k}\rfloor}{m}\frac{1}{1-\frac{\lfloor\frac{m}{k}\rfloor}{m}}\\ &= 1-\sum_{k\geq 2}\mu(k)\frac{\lfloor\frac{m}{k}\rfloor}{m-\lfloor\frac{m}{k}\rfloor}\\ \end{align} \]

其中用了期望定义、容斥、莫反、等比数列求和公式。

解释:

\((1)\) 没什么好说的,就是期望的定义。

\((2)、(3)、(4)\) 就是先将 \(j\) 拆开,然后交换求和顺序,之后再将其中一个求和拍到概率种统一算。

其实这几步甚至可以不用推,直接瞪眼法可以一步想到,还是挺套路的。如果是第一次见,可以记一下,当套路食用。

\((5)\) 就是将等号提出来,之后 \((6)\) 就是将式子按照题目的定义将 \(P\) 写出来。

\((7)\) 这里运用了莫比乌斯反演,这玩意几个结论就好。

同时注意,由于每个位置选某个数的概率是 \(\frac{1}{m}\),所以 \(i\) 个数就是 \(\frac{1}{m^i}\),之后又将 \(1\) 挪到了分数线上面。

\((8)\) 就是把 \(k=1\) 拿出来,\((9)\) 是把符号提出去,之后变换求和顺序到 \((10)\)

注意到 \((10)\) 就是个等比数列求和,直接套公式到 \((11)\)

又由于 \(\frac{\lfloor\frac{m}{k}\rfloor}{m}<1\),所以当 \(n\) 趋近于 \(\infty\) 时,它的 \(n\) 次方就是 \(0\)

那么就变到 \((12)\),之后乘在一起就是 \((13)\)

到了这一步,这个式子就十分的简洁了,可以直接枚举 \(k\),上界显然就是 \(m\) 因为 \(k>m\) 时对答案的贡献就都是 \(0\)

复杂度 \(O(m)\)

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007ll
inline int read(){
	int rt=0;	char g=getchar();
	while(g<'0'||g>'9')	g=getchar();
	while(g>='0'&&g<='9')	rt=(rt<<3)+(rt<<1)+g-'0',g=getchar();
	return rt;
}
inline int KSM(int A,int k)
{
	if(!k)	return 1;
	ll rt=KSM(A,k>>1);
	(rt*=rt)%=mod;
	if(k&1)	(rt*=1ll*A)%=mod;
	return rt;
}

int n;
ll ans;
bool ck[100005];
ll mu[100005],p[100005],num;
int main()
{
	n=read();	mu[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!ck[i])	p[++num]=i,mu[i]=-1;
		for(int j=1;j<=num&&p[j]*i<=n;j++)
		{
			ck[p[j]*i]=1;
			if(!(i%p[j]))	break;
			mu[p[j]*i]=-mu[i];
		}
	}
	for(int i=2;i<=n;i++)(ans+=mu[i]*(n/i)%mod*KSM((n-n/i),(mod-2))%mod)%=mod;
	printf("%lld",(1ll-ans+mod)%mod);
	return 0;
}
posted @ 2024-07-30 19:57  YT0104  阅读(11)  评论(0编辑  收藏  举报