题面
一个数列,每次随机选一个 ([1,m]) 之间的数加在数列末尾,数列中所有数的 (gcd=1) 时停止,求期望长度 (mod 10^9+7)。
数据范围:(1le mle 10^5)。
蒟蒻语
这题的非 dp 做法讲得太玄了而且写题解的人貌似不屑于解释,于是蒟蒻来写一篇。
(其实是 ubuntu 剪贴板炸了没得记录题目了只好写题解了)。
蒟蒻解
先推一波概率期望式((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;
}
祝大家学习愉快!