• bzoj2005: [Noi2010]能量采集


    感觉莫反学的很不扎实。。很虚。。bs lmy

    为什么这么说,是因为我连求F(i)要把他转换成F(1)再求都不知道。。。。

    那么这题抽象点看ans就是等于这个

    ans = n*m + sigema(1~n)x sigema(1~m)y (gcd(x,y)-1)*2

    F(i)表示 gcd(x,y)==i 的个数,那么ans = n*m + sigema(1~n)i (n-1)*2*F(i)

    G(i)表示 gcd(x,y)==i的倍数 的个数

    那么G(i)=(n/i)*(m/i)

    然后反演形式2 F(i)=sigma(u(d/i)*G(d)) (其中n|d)

    PS(无脑long long)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    LL pr,prime[110000],u[110000];
    bool v[110000];
    void mobius_inversion()
    {
        pr=0;u[1]=1;
        memset(v,true,sizeof(v));
        for(int i=2;i<=100000;i++)
        {
            if(v[i]==true)
            {
                prime[++pr]=i;
                u[i]=-1;
            }
            for(int j=1;j<=pr&&i*prime[j]<=100000;j++)
            {
                v[i*prime[j]]=false;
                if(i%prime[j]==0){u[i*prime[j]]=0;break;}
                u[i*prime[j]]=-u[i];
            }
            u[i]+=u[i-1];
        }
    }
    
    LL getFi(LL n,LL m)
    {
        LL t=min(n,m),last;LL Fi=0;
        for(LL d=1;d<=t;d=last+1)
        {
            last=min(n/(n/d),m/(m/d));
            LL Gd=(n/d)*(m/d);
            Fi+=(u[last]-u[d-1])*Gd;
        }
        return Fi;
    }
    int main()
    {
        mobius_inversion();
        
        LL n,m;
        scanf("%lld%lld",&n,&m);
        if(n>m)swap(n,m);
        
        LL ans=n*m;
        for(int i=1;i<=n;i++)
        {
            ans+=(i-1)*2*getFi(n/i,m/i);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    java-五子棋棋盘排布 && 数字转换成汉字 &&大数计算
    动手动脑,无法自拔(2)课时作业4
    动手动脑,无法自拔(1)课时作业3
    《大道至简》 第二章 读后感
    NABCD需求
    第九周总结
    第八周总结
    最大子数组(循环连接)
    第七周总结
    最大子数组和
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/7903819.html
Copyright © 2020-2023  润新知