[BZOJ4407]于神之怒加强版(莫比乌斯反演)

题目描述

传送门

题解

感觉这题非常强
假设 n<m

i=1nj=1m(i,j)k

=i=1nj=1md=1n[(i,j)=d]dk

=d=1ndki=1ndj=1md[(i,j)=1]

用一下反演公式 [n=1]=d|nμ(d)
=d=1ndki=1ndj=1mdt|(i,j)μ(t)

=d=1ndkt=1ndi=1nd[t|i]j=1md[t|j]μ(t)

=d=1ndkt=1ndndtmdtμ(t)

T=dt ,此时 d T的约数
=T=1nnTmTd|Tμ(Td)dk

发现最后的 d|Tμ(Td)dk 就是狄利克雷卷积的形式
g(n)=nk,f(n)=d|nμ(nd)g(d)
μ g 都是积性函数,所以f=μ×g也是一个积性函数
那么可以用线性筛求 f
a为质数时显然 f(a)=ak1
(a,b)=1 f(ab)=f(a)f(b)
ab 不互质时,也就是用 f(pkii) pi 计算 f(pki+1i) 时,利用莫比乌斯函数的性质,发现只有 μ(1) μ(pi) 是有价值的
f(pkii)=μ(1)(pkii)k+μ(pi)(pki1i)k
f(pki+1i)=μ(1)(pki+1i)k+μ(pi)(pkii)k
也就是说 f(pki+1i)=f(pkii)pki
那么就可以筛筛筛了
计算出来 f(n) 了之后原式变成了
T=1nnTmTf(T)

预处理出 f(n) 的前缀和,只有 O(n+m) 种取值
分块求解
时间 O(n+T(n+m))

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define Mod 1000000007
#define LL long long
#define N 5000005

int T,n,m,k;
int p[N],prime[N];
LL ans,f[N];

LL fast_pow(LL a,int p)
{
    LL ans=1;
    for (;p;p>>=1,a=a*a%Mod)
        if (p&1)
            ans=ans*a%Mod;
    return ans;
}
void get(int n)
{
    f[1]=1;
    for (int i=2;i<=n;++i)
    {
        if (!p[i])
        {
            prime[++prime[0]]=i;
            f[i]=(fast_pow(i,k)-1+Mod)%Mod;
        }
        for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
        {
            p[i*prime[j]]=1;
            if (i%prime[j]==0)
            {
                f[i*prime[j]]=f[i]*fast_pow(prime[j],k)%Mod;
                break;
            }
            else f[i*prime[j]]=f[i]*f[prime[j]]%Mod;
        }
    }
    for (int i=2;i<=n;++i) f[i]=(f[i]+f[i-1])%Mod;
}
int main()
{
    scanf("%d%d",&T,&k);
    get(5000000);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        ans=0;
        for (int i=1,j=0;i<=n;i=j+1)
        {
            j=min(n/(n/i),m/(m/i));
            ans+=(f[j]-f[i-1])*(n/i)%Mod*(m/i)%Mod;
            ans=(ans%Mod+Mod)%Mod;
        }
        printf("%lld\n",ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值