洛谷 P4449 于神之怒加强版 莫比乌斯反演

Description

给下N,M,K.求
这里写图片描述

Input

输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意义如上式所示。
Output

如题
Sample Input

1 2

3 3
Sample Output

20

HINT

1<=N,M,K<=5000000,1<=T<=2000

分析:一道非常显然的莫比乌斯反演题目啦。不过要知道的是两个积性函数的狄利克雷卷积也是一个积性函数。

代码:

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long

const LL maxn=5e6+7;
const LL mod=1000000007;

using namespace std;

LL test,n,m,k,cnt;
LL prime[maxn],not_prime[maxn];
LL f[maxn],g[maxn];

LL power(LL x,LL y)
{
    if (y==1) return x;
    LL d=power(x,y/2);
    d=(d*d)%mod;
    if (y%2) d=(d*x)%mod;
    return d;
}

void getmul(LL n)
{
    f[1]=1;
    for (LL i=2;i<=n;i++)
    {
        if (!not_prime[i])
        {
            prime[++cnt]=i;
            g[i]=power((LL)i,k);
            f[i]=(g[i]+mod-1)%mod;
        }
        for (LL j=1;j<=cnt;j++)
        {
            if (i*prime[j]>n) break;
            not_prime[i*prime[j]]=1;
            if (i%prime[j]==0)
            {
                f[i*prime[j]]=(f[i]*g[prime[j]])%mod;
                break;
            }
            f[i*prime[j]]=(f[i]*f[prime[j]])%mod;
        }
    }
    for (LL i=1;i<=n;i++) f[i]=(f[i-1]+f[i])%mod;
}

LL calc(LL n,LL m)
{
    LL ans=0;
    if (n>m) swap(n,m);
    for (LL i=1,last;i<=n;i=last+1)
    {
        last=min(n/(n/i),m/(m/i));
        ans=(LL)(ans+(n/i)*(m/i)%mod*(f[last]+mod-f[i-1])%mod)%mod;
    }
    return ans;
}
int main()
{
    scanf("%lld%lld",&test,&k); 
    getmul(maxn);       
    while (test--)
    {
        scanf("%lld%lld",&n,&m);        
        printf("%lld\n",calc(n,m));
    }
}

猜你喜欢

转载自blog.csdn.net/liangzihao1/article/details/80161971