題目鏈接
前置推論:
1.長度爲1的序列只可能是一個1。
2.假設當前的序列長度爲,且前個數的不爲1的話,那麼第位的數必然與a互質,所以第個數選擇的方案爲[1,m]中與a互質的數的個數,記爲中與a互質的數的個數,可以通過容斥計算。
那麼我們需要統計的就是所有長度>=2的期望。
我們從大到小遍歷,設當前枚舉到的數爲x,我們計算所有長度爲且序列的前i項的爲x的期望,那麼可以前i項必然都是x的倍數,顯然通過求和我們可以得到一個較大的答案
其中爲常數項可以拎出來單獨計算,那麼後面的就是我們要求的,這樣求和的東西就是高中常說的錯位相減法搞一下就能算出來了。
但是爲什麼說這個答案較大呢?仔細想一下,這樣生成的序列的前i項的gcd必然包含所有x的倍數。
設爲序列長度爲dx且gcd爲dy的概率
那麼後半部分真正的答案就是
我們設,那麼,那麼長度爲i+1項且前i項的gcd爲x的真正期望就是。
綜上,對每個數進行討論並計算答案即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
LL m;
const LL mod=1e9+7;
LL pm(LL x,LL y){
LL z=1;
while(y){
if(y&1)z=z*x%mod;
x=x*x%mod;
y>>=1;
}
return z;
}
int a[N],p[N],cnt;
void P(){
for(int i=2;i<N;i++){
if(!p[i])a[++cnt]=i;
for(int j=1;j<=cnt&&1ll*a[j]*i<N;j++){
p[a[j]*i]=1;
if(i%a[j]==0)break;
}
}
}
LL get(int y){
vector<int>x;
for(int i=1;i<=cnt&&1ll*a[i]*a[i]<=y;i++){
if(y%a[i]==0){
x.pb(a[i]);
while(y%a[i]==0)y/=a[i];
}
}
if(y>1)x.pb(y);
int sz=x.size();
int ans=m;
for(int i=1;i<1<<sz;i++){
int l=0,r=1;
for(int j=0;j<sz;j++){
if(1<<j&i){
l++;
r*=x[j];
}
}
if(l&1)ans-=m/r;
else ans+=m/r;
}
return ans;
}
LL _get(LL x){
return (x*(m-x)+x*m)%mod*pm(1ll*(m-x)*(m-x)%mod,mod-2)%mod;
}
LL an[N];
int main() {
ios::sync_with_stdio(false);
cin>>m;P();
LL re_m=pm(m,mod-2);
LL ans=re_m;
for(int i=m;i>=2;i--){
LL x=get(i);
LL res=_get(m/i)%mod;
for(int j=i+i;j<=m;j+=i)res-=an[j],res=(res+mod)%mod;
an[i]=res;
ans+=res*x%mod*re_m%mod;
ans%=mod;
}
cout<<ans<<'\n';
return 0;
}