bzoj 4407: 于神之怒加强版

题意:求
nimjgcd(i,j)k mod 109+7

题解:

先上经典的莫比乌斯反演变形得到:

min(n,m)d=1dkmin(nd,md)p=1μ(p)ndpmdp

=min(n,m)T=1nTmTd|Tddkμ(Td)

设f(T)= dd|Tdkμ(Td)
关键要求f的前缀和。
orz

ps:注意int,long long 的转换

code:

#include
#include
#include
#include
#define LL long long
using namespace std;
LL prime[5000010],f[5000010],p[5000010];
int pr,k;
bool v[5000010];
const LL mod=1000000007;
LL work(LL a,int b)
{
    LL ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;b>>=1;
    }
    return ans;
}
void pre()
{
    memset(v,true,sizeof(v));
    pr=0;f[1]=1;
    for(int i=2;i<=5000000;i++)
    {
        if(v[i])
        {
            prime[++pr]=(LL)i;
            f[i]=(work(i,k)-1)%mod;
        }
        for(int j=1;j<=pr&&(LL)i*prime[j]<=5000000;j++)
        {
            v[i*prime[j]]=false;
            if(i%prime[j]==0){f[i*prime[j]]=(f[i]*work(prime[j],k))%mod;break;}
            f[i*prime[j]]=(f[i]*f[prime[j]])%mod;
        }
    }
    for(int i=2;i<=5000000;i++) f[i]=(f[i]+f[i-1])%mod;
}
int main()
{
    int T;scanf("%d %d",&T,&k);
    pre();
    while(T--)
    {
        int n,m;scanf("%d %d",&n,&m);
        LL ans=0;int j;
        if(n>m) swap(n,m);
        for(int i=1;i<=n;i=j+1)
        {
            j=min(n/(n/i),m/(m/i));
            ans=(ans+(LL)(n/i)*(LL)(m/i)%mod*((f[j]-f[i-1]+mod)%mod)%mod)%mod;
        }
        printf("%lld\n",(ans+mod)%mod);
    }
}

你可能感兴趣的:(数论,莫比乌斯反演,筛法)