此题学到一招,就是将概率dp转化为DAG图
考虑概率f[],设f[i]表示当前数组的gcd为i是走向gcd为1的期望步数,因为每次可以选择一个数(1 , m) ,添加到结尾,所以相当于每次从当前x点走向gcd(x , k) , 所以从每个点走,都有m条路径,,最后加一个虚点, 连接第一次选择的数,所以答案也就相当于从虚点走向1,只要求从虚点走向第一次选择的点就可, 答案:
a
n
s
=
1
+
∑
1
m
f
[
i
]
m
ans = 1 + \frac{\sum_{1}^{m}{f[i]}}{m}
ans=1+m∑1mf[i]
考虑怎么求f[n] , 从点n可以走向
d
,
[
d
∣
n
]
d , [d | n]
d,[d∣n] , 所以
f
[
n
]
=
1
+
∑
i
=
1
m
f
[
g
c
d
(
n
,
i
)
]
m
f[n] = 1 + \frac{\sum_{i = 1}^{m}{f[gcd(n , i)]}}{m}
f[n]=1+m∑i=1mf[gcd(n,i)]
=
>
m
∗
f
[
n
]
=
m
+
∑
i
=
1
m
f
[
g
c
d
(
n
,
i
)
]
\\=>m * f[n] = m + \sum_{i = 1}^{m}{f[gcd(n , i)]}
=>m∗f[n]=m+i=1∑mf[gcd(n,i)]
=
>
m
∗
f
[
n
]
=
m
+
∑
d
∣
n
f
[
d
]
∗
∑
[
g
c
d
(
n
,
i
)
=
=
d
]
\\=>m * f[n] = m + \sum_{d |n}{f[d] * \sum[gcd(n , i) == d]}
=>m∗f[n]=m+d∣n∑f[d]∗∑[gcd(n,i)==d]下面是莫比乌斯反演
=
>
∑
i
=
1
m
[
g
c
d
(
n
,
i
)
=
=
d
]
\\=>\sum_{i = 1}^{m}[gcd(n , i) == d]
=>i=1∑m[gcd(n,i)==d]
=
>
∑
i
=
1
m
d
[
g
c
d
(
n
d
,
i
)
=
=
1
]
\\=>\sum_{i = 1}^{\frac{m}{d}}[gcd(\frac{n}{d} , i) == 1]
=>i=1∑dm[gcd(dn,i)==1]
=
>
∑
i
=
1
m
d
∑
t
∣
g
c
d
(
n
d
,
i
)
μ
(
t
)
\\=>\sum_{i = 1}^{\frac{m}{d}}\sum_{t|gcd(\frac{n}{d} , i)}\mu(t)
=>i=1∑dmt∣gcd(dn,i)∑μ(t)
=
>
∑
i
=
1
m
d
∑
t
∣
n
d
&
t
∣
i
μ
(
t
)
\\=>\sum_{i = 1}^{\frac{m}{d}}\sum_{t|\frac{n}{d} \&t|i}\mu(t)
=>i=1∑dmt∣dn&t∣i∑μ(t)
=
>
∑
t
∣
n
d
μ
(
t
)
∗
⌊
m
d
∗
t
⌋
\\=>\sum_{t|\frac{n}{d}}\mu(t) * \lfloor\frac{m}{d*t}\rfloor
=>t∣dn∑μ(t)∗⌊d∗tm⌋
带
回
原
式
带回原式
带回原式
=
>
m
∗
f
[
n
]
=
m
+
∑
d
∣
n
f
[
d
]
∗
(
∑
t
∣
n
d
μ
(
t
)
∗
⌊
m
d
∗
t
⌋
)
=>m * f[n] = m + \sum_{d |n}{f[d] * (\sum_{t|\frac{n}{d}}\mu(t) * \lfloor\frac{m}{d*t}\rfloor)}
=>m∗f[n]=m+d∣n∑f[d]∗(t∣dn∑μ(t)∗⌊d∗tm⌋)
这个时候发现在枚举d的时候d有可能等于n, n也是n的约数, 拿出来之后
m
∗
f
[
n
]
=
m
+
∑
d
∣
n
&
d
!
=
n
f
[
d
]
∗
(
∑
t
∣
n
d
μ
(
t
)
∗
⌊
m
d
∗
t
⌋
)
+
f
[
n
]
∗
⌊
m
n
⌋
m * f[n] = m + \sum_{d |n\&d!=n}{f[d] * (\sum_{t|\frac{n}{d}}\mu(t) * \lfloor\frac{m}{d*t}\rfloor)} + f[n] * \lfloor\frac{m}{n}\rfloor
m∗f[n]=m+d∣n&d!=n∑f[d]∗(t∣dn∑μ(t)∗⌊d∗tm⌋)+f[n]∗⌊nm⌋
=
>
f
[
n
]
=
m
+
∑
d
∣
n
&
d
!
=
n
f
[
d
]
∗
(
∑
t
∣
n
d
μ
(
t
)
∗
⌊
m
d
∗
t
⌋
)
m
−
⌊
m
n
⌋
+
=>f[n] = \frac{m + \sum_{d |n\&d!=n}{f[d] * (\sum_{t|\frac{n}{d}}\mu(t) * \lfloor\frac{m}{d*t}\rfloor)}}{m - \lfloor\frac{m}{n}\rfloor} +
=>f[n]=m−⌊nm⌋m+∑d∣n&d!=nf[d]∗(∑t∣dnμ(t)∗⌊d∗tm⌋)+
这个复杂度我不知道是怎么过的,先预处理出来 μ ( t ) \mu(t) μ(t) , 预处理每个数的约数, 然后先枚举n,再枚举d,最后枚举t
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <stack>
#include <set>
#pragma GCC optimize(3 , "Ofast" , "inline")
using namespace std ;
#define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
#define x first
#define y second
typedef long long ll ;
const double esp = 1e-6 , pi = acos(-1) ;
typedef pair<int , int> PII ;
const int N = 2e5 + 10 , INF = 0x3f3f3f3f , mod = 1e9 + 7;
ll in()
{
ll x = 0 , f = 1 ;
char ch = getchar() ;
while(!isdigit(ch)) {if(ch == '-') f = -1 ; ch = getchar() ;}
while(isdigit(ch)) x = x * 10 + ch - 48 , ch = getchar() ;
return x * f ;
}
ll mu[N] , tot , prime[N] , vis[N] , f[N] , inv[N] ;
vector<ll> v[N] ;
int main()
{
ll m = in() ;
mu[1] = 1 ;
for(ll i = 2; i < N ;i ++ ) {
if(!vis[i]) prime[++ tot] = i , mu[i] = -1 ;
for(ll j = 1 ;j <= tot && i * prime[j] < N ;j ++ )
{
vis[i * prime[j]] = 1 ;
if(i % prime[j] == 0) break ;
mu[i * prime[j]] = - mu[i] ;
}
}
inv[1] = 1 ;
for(ll i = 2; i < N ;i ++ )
inv[i] = (mod - mod / i) * inv[mod % i] % mod ;
f[1] = 0 ;
for(ll i = 1; i < N ;i ++ ) {
for(ll j = i ;j < N ;j += i)
v[j].push_back(i) ;
}
for(ll i = 2; i <= m ;i ++ ) {
ll n = i ;
ll ans = m ;
for(auto d : v[n]) {
if(d == n) break ;
ll res = 0 ;
for(auto t : v[n / d]) {
res += mu[t] * (m / d / t) % mod ;
res %= mod ;
}
res = res * f[d] % mod ;
(ans += res) %= mod ;
}
ans = ans * inv[m - m / n] % mod ;
f[i] = ans ;
}
ll ans = 0 ;
for(int i = 1; i <= m ;i ++ )
(ans += f[i]) %= mod ;
ans = ans * inv[m] % mod ;
ans ++ ;
cout << ans << endl ;
return 0 ;
}
/*
*/