• bzoj 3561


    题意:求$sum_{i=1}^{n}sum_{j=1}^{n}lcm(i,j)^{gcd(i,j)}$

    神仙题...

    首先可能会想到一个转化,就是$lcm(i,j)=frac{ij}{gcd(i,j)}$

    然后大力往下推式子,发现你推不下去了...

    因为$d$在分母上!!!

    然后我们考虑换一种推法:如果我们对$ij$同时除掉$gcd(i,j)$,这样的话问题就可以转化成这个样子:

    $sum_{d=1}^{n}sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}}[gcd(i,j)equiv 1](ijd)^{d}$

    然后把$d$拿出来,维护一下后面那坨,有:

    $sum_{d=1}^{n}d^{d}sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}}sum_{t|gcd(i,j)}mu(t)(ij)^{d}$

    改变一下枚举顺序,得到:

    $sum_{d=1}^{n}d^{d}sum_{t=1}^{frac{n}{d}}mu(t)sum_{i=1}^{frac{n}{dt}}sum_{j=1}^{frac{m}{dt}}(ijt^{2})^{d}$

    (也就是在后面的$ij$乘积这一项中单独考虑$t$的贡献)

    然后再整理,就得到:

    $sum_{d=1}^{n}d^{d}sum_{t=1}^{frac{n}{d}}mu(t)t^{2d}sum_{i=1}^{frac{n}{dt}}i^{d}sum_{j=1}^{frac{m}{dt}}j^{d}$

    然后我们就暴力计算即可,每次计算时都要先预处理出$[1,frac{n}{d}]$的$i^{d}$的前缀和,再暴力查询即可,时间复杂度为调和级数$O(nlnn)$

    注意每次求幂可以递推,不要快速幂!!!会退化成$O(nlog_{2}^{2}n)$!

    代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const ll mode=1000000007;
    int pri[5000005],mu[5000005],used[5000005];
    ll S[5000005],mi[5000005];
    int cnt=0;
    ll pow_mul(ll x,ll y)
    {
        ll ret=1;
        while(y)
        {
            if(y&1)ret=ret*x%mode;
            x=x*x%mode,y>>=1;
        }
        return ret;
    }
    void init()
    {
        mu[1]=1;
        for(int i=2;i<=5000000;i++)
        {
            if(!used[i])pri[++cnt]=i,mu[i]=-1;
            for(int j=1;j<=cnt&&i*pri[j]<=5000000;j++)
            {
                used[i*pri[j]]=1;
                if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
                mu[i*pri[j]]=-mu[i];
            }
        }
    }
    int main()
    {
        init();
        ll n,m;
        scanf("%lld%lld",&n,&m);
        if(n>m)swap(n,m);
        ll ans=0;
        for(int i=1;i<=m;i++)mi[i]=1;
        for(int i=1;i<=n;i++)
        {
            ll s=pow_mul(i,i);
            S[0]=0;
            for(int j=1;j<=m/i;j++)mi[j]=mi[j]*j%mode,S[j]=(S[j-1]+mi[j])%mode;
            ll tempc=0;
            for(int j=1;j<=n/i;j++)
            {
                ll temps=(mu[j]*mi[j]*mi[j]%mode+mode)%mode;
                tempc=(tempc+temps*S[n/i/j]%mode*S[m/i/j]%mode)%mode;
            }
            ans=(ans+s*tempc)%mode;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Windows中Lua环境配置记录
    《Programming in Lua 3》读书笔记(四)
    《Programming in Lua 3》读书笔记(三)
    《Programming in Lua 3》读书笔记(一)
    C++中的struct
    POJ 1080 Human Gene Functions
    POJ 3176 Cow Bowling
    POJ 2533 Longest Ordered Subsequence
    POJ 1260 Pearls
    POJ 1836 Alignment
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11150963.html
Copyright © 2020-2023  润新知