3309: DZY Loves Math 莫比乌斯反演

F(i) 表示 i 所含质因子最大幂指数,f(i)表示 gcd(x,y)=i 的数对 (x,y) 的数量,然后莫比乌斯反演得到下式:

Ans=T=1nnTmTdTF(d)μ(Td)

G(T)=dTF(d)μ(Td) ,然后我们大力讨论一下。
首先设 T=Px11×Px22×..×Pxkk,d==Py11×Py22×..×Pykk
要使 μ(Td)0 ,必须满足 yi=xi 或者 yi=xi1
a=Max1ik(xi) ,则 F(d)=a a1
假设 T 中一共有q个质因子的指数为 a

一、当q=k时,
f(d)=a

f(d)=af(d)μ(Td)=a×f(d)=aμ(Td)=a×i=1k(1)kiCik=a×(1)k+1

f(d)=a1
f(d)=a1f(d)μ(Td)=(a1)×f(d)=a1μ(Td)=(a1)×(1)k

所以当 q=k 时, G(T)=a×(1)k+1+(a1)×(1)k=(1)k+1
二、当 q<k
f(d)=a
f(d)=af(d)μ(Td)=a×f(d)=aμ(Td)=a×i=1q(1)qiCiq×j=0kq(1)jCjkq=0

f(d)=a1
f(d)=a1f(d)μ(Td)=(a1)×f(d)=a1μ(Td)=(a1)×(1)q×j=0kq(1)jCjkq=0

所以当 q<k 时, G(T)=0
知道这些,我们可以线筛的时候记录一下最小质因子出现的次数和除去最小质因子 px11 后的数,然后判断幂指数是否相等。

#include<iostream>
#include<cstdio>
#define ll long long 
#define MAXN 10000005
using namespace std;
int prime[MAXN],t[MAXN],last[MAXN];
ll g[MAXN];
bool flag[MAXN];
inline ll read()
{
    ll a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline void prepare()
{
    for (int i=2;i<MAXN;i++)
    {
        if (!flag[i]) prime[++prime[0]]=i,last[i]=t[i]=g[i]=1;
        for (int j=1;j<=prime[0]&&i*prime[j]<MAXN;j++)
        {
            flag[i*prime[j]]=1;
            if (i%prime[j]==0)
            {
                last[i*prime[j]]=last[i];
                t[i*prime[j]]=t[i]+1;
                if (last[i*prime[j]]==1) g[i*prime[j]]=1;
                else g[i*prime[j]]=(t[last[i*prime[j]]]==t[i*prime[j]]?-g[last[i*prime[j]]]:0);
                break;
            }
            last[i*prime[j]]=i;
            t[i*prime[j]]=1;
            g[i*prime[j]]=(t[i]==1?-g[i]:0);
        }
    }
    for (int i=1;i<MAXN;i++) g[i]+=g[i-1];
}
inline ll solve(ll n,ll m)
{
    ll ans=0;
    for (int i=1,pos;i<=n;i=pos+1)
    {
        pos=min(n/(n/i),m/(m/i));
        ans+=(g[pos]-g[i-1])*(n/i)*(m/i);
    }
    return ans;
}
int main()
{
    prepare();
    int testcase=read();
    while (testcase--)
    {
        ll n=read(),m=read();
        if (n>m) swap(n,m);
        printf("%lld\n",solve(n,m));
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值