• Codeforces


     蒟蒻数学渣呀,根本不会做。

    解法是参考 https://blog.csdn.net/xs18952904/article/details/88785210 这位大佬的。

    状态的设计和转移如上面博客一样:dp[i]代表当前序列的gcd为i的期望长度。

    那么可以写出状态转移方程:dp[i]=(1+(x/m)∑(j|i,j≠i)dp[j]) / (1-(m/i)/m) (写得有点乱,其实和上面大佬的一样的)

    这里要说一下的是 x=∑(t=1,t<=m) [ gcd(t,i)==j ]  就是怎么求1<=t<=m 中gcd(t,i)=j的t的个数。

    这里考虑莫比乌斯反演:

    x=∑(t=1,t<=m)[gcd(t,i)=j] 

    把j提出来 x=∑(t=1,t<=m/j) [gcd(t,i/j)=1] 

    代入莫比乌斯性质:x=∑(t=1,t<=m) ∑(d|gcd(t,i/j)) μ(d)

    套路,改为枚举d : x=(m/jd)(d|(i/j)) μ(d)

    这样就可以求出x了,这道题就可以解决了。

    时间复杂度为O(m*log(m)*因子个数)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1e5+10;
    const int MOD=1e9+7;
    LL m,mu[N],v[N],dp[N];
    
    LL power(LL x,LL p) {
        LL ret=1;
        for (;p;p>>=1) {
            if (p&1) ret=(ret*x)%MOD;
            x=(x*x)%MOD;
        }
        return ret;
    }
    
    vector<int> fac[N];
    void prework() {
        for (int i=1;i<=m;i++)
            for (int j=1;j<=m/i;j++)
                fac[i*j].push_back(i);        
        for (int i=1;i<=m;i++) mu[i]=1,v[i]=0;
        for (int i=2;i<=m;i++) {
            if (v[i]) continue;
            mu[i]=-1;
            for (int j=2*i;j<=m;j+=i) {
                v[j]=1;
                if ((j/i)%i==0) mu[j]=0;
                else mu[j]*=-1;
            }
        }
    }
    
    LL calc(LL i,LL j) {
        LL ret=0;
        for (int k=0;k<fac[i/j].size();k++) {
            int d=fac[i/j][k];
            LL tmp=(mu[d]+MOD)%MOD*(m/j/d)%MOD;
            ret=(ret+tmp)%MOD;
        }
        return ret;
    }
    
    int main()
    {
        cin>>m;
        prework();
        LL ans=1; dp[1]=0;
        for (int i=2;i<=m;i++) {
            dp[i]=0;
            for (int j=0;j<fac[i].size();j++) {
                if (fac[i][j]==i) continue;
                LL x=calc(i,fac[i][j]);
                dp[i]=(dp[i]+x*dp[fac[i][j]]%MOD)%MOD;
            }
            dp[i]=dp[i]*power(m,MOD-2)%MOD;
            dp[i]=(dp[i]+1)%MOD;
            dp[i]=(dp[i]*m%MOD*power(m-m/i,MOD-2))%MOD;
            ans=(ans+dp[i]*power(m,MOD-2)%MOD)%MOD;
        }
        cout<<ans<<endl;
        return 0;
    } 
  • 相关阅读:
    习题10-2 递归求阶乘和(15 分)
    在过滤器中得到模型状态信息
    理解OAuth 2.0
    asp.net mvc 控制器的依赖注入(使用Ninject)
    web.routing 学习
    深度优先和广度优先的基础应用
    数的全排
    C# 表达式树
    C#中RSA的简单使用
    select into 和insert into select
  • 原文地址:https://www.cnblogs.com/clno1/p/10813029.html
Copyright © 2020-2023  润新知