CF1139D Steps to One
很好的一道题。
最开始我想的是 ,但是在序列 不变的时候有点想不明白。
后来看了几位大佬的思路,终于会了。
CF1139D Steps to One
题目大意:
一个初始为空的数列,每次等概率随机在末尾放入一个 到 之间的数,序列 时结束,问序列长度的期望。
题目思路:
如果你实在是不会什么方法,那就直接推式子,先将期望的定义写出来,之后一步步化简。
令 为步数:
(解释在后面)
式子:
其中用了期望定义、容斥、莫反、等比数列求和公式。
解释:
没什么好说的,就是期望的定义。
就是先将 拆开,然后交换求和顺序,之后再将其中一个求和拍到概率种统一算。
其实这几步甚至可以不用推,直接瞪眼法可以一步想到,还是挺套路的。如果是第一次见,可以记一下,当套路食用。
就是将等号提出来,之后 就是将式子按照题目的定义将 写出来。
这里运用了莫比乌斯反演,这玩意几个结论就好。
同时注意,由于每个位置选某个数的概率是 ,所以 个数就是 ,之后又将 挪到了分数线上面。
就是把 拿出来, 是把符号提出去,之后变换求和顺序到 。
注意到 就是个等比数列求和,直接套公式到 。
又由于 ,所以当 趋近于 时,它的 次方就是 。
那么就变到 ,之后乘在一起就是 。
到了这一步,这个式子就十分的简洁了,可以直接枚举 ,上界显然就是 因为 时对答案的贡献就都是 。
复杂度 。
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现