正题
题目链接:https://www.luogu.com.cn/problem/CF1139D
题目大意
不停的在表格中填下1∼m1\sim m1∼m中随机一个数,直到所有数的gcd=1gcd=1gcd=1为止,求期望数的个数。
解题思路
设fnf_nfn表示现在gcdgcdgcd为nnn时的期望个数。那么有转移方程fn=∑i=1mfgcd(i,n)m+1f_n=\frac{\sum_{i=1}^mf_{gcd(i,n)}}{m}+1fn=m∑i=1mfgcd(i,n)+1
为了方便,我们先把其中⌊mn⌋\lfloor\frac{m}{n}\rfloor⌊nm⌋个gcd(i,n)=ngcd(i,n)=ngcd(i,n)=n的提出来,我们在后面的计算中均以其为000。
如果我们求出一个函数h(x)=∑i=1m[gcd(i,n)==x]h(x)=\sum_{i=1}^m[gcd(i,n)==x]h(x)=∑i=1m[gcd(i,n)==x]那么方程就可以转换成方便的形式,因为显然只有x∣nx|nx∣n时h(x)h(x)h(x)才有值。
考虑如何求这个hhh,直接上莫反H(x)=∑x∣dh(d)=⌊mx⌋∗[x∣n]H(x)=\sum_{x|d}h(d)=\lfloor\frac{m}{x}\rfloor*[x|n]H(x)=x∣d∑h(d)=⌊xm⌋∗[x∣n]
ans=∑x∣nh(x)fx=∑x∣nfx∑x∣yH(y)μ(yx)=∑x∣nfx∑x∣y,y∣n⌊mx⌋μ(yx)ans=\sum_{x|n}h(x)f_x=\sum_{x|n}f_x\sum_{x|y}H(y)\mu(\frac{y}{x})=\sum_{x|n}f_x\sum_{x|y,y|n}\lfloor\frac{m}{x}\rfloor\mu(\frac{y}{x})ans=x∣n∑h(x)fx=x∣n∑fxx∣y∑H(y)μ(xy)=x∣n∑fxx∣y,y∣n∑⌊xm⌋μ(xy)
这个很麻烦计算,把yyy提出来
⇒∑y∣n⌊mx⌋∑x∣yμ(yx)fx\Rightarrow\sum_{y|n}\lfloor\frac{m}{x}\rfloor\sum_{x|y}\mu(\frac{y}{x})f_x⇒y∣n∑⌊xm⌋x∣y∑μ(xy)fx
后面那个做完一个fff就预处理一个,然后跟着转移即可。
时间复杂度O(mm)O(m\sqrt m)O(mm)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10,P=1e9+7;
ll m,cnt,pri[N],mu[N],f[N],g[N];
bool v[N];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
void prime(){mu[1]=1;for(ll i=2;i<=m;i++){if(!v[i])pri[++cnt]=i,mu[i]=-1;for(ll j=1;j<=cnt&&i*pri[j]<=m;j++){v[i*pri[j]]=1;if(i%pri[j]==0)break;mu[i*pri[j]]=mu[i]*mu[pri[j]];}}return;}
signed main()
{scanf("%lld",&m);prime();ll ans=f[1]=g[1]=1;for(ll n=2;n<=m;n++){for(ll i=1;i*i<=n;i++)if(n%i==0){if(i*i!=n)(g[n]+=mu[i]*f[n/i]%P)%=P;(g[n]+=mu[n/i]*f[i]%P)%=P;}for(ll i=1;i*i<=n;i++)if(n%i==0){if(i*i!=n)(f[n]+=(m/(n/i))*g[n/i]%P)%=P;(f[n]+=(m/i)*g[i]%P)%=P;}f[n]=(f[n]+m)%P*power(m-m/n,P-2)%P;ans=(ans+f[n])%P;(g[n]+=f[n])%=P;}ans=ans*power(m,P-2)%P;printf("%lld\n",(ans+P)%P);return 0;
}