Luogu2257 YY的GCD

原题链接:https://www.luogu.org/problemnew/show/P2257

YY的GCD

题目描述

神犇YY虐完数论后给傻×kAc出了一题

给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对

kAc这种傻×必然不会了,于是向你来请教……

多组输入

输入输出格式
输入格式:

第一行一个整数T 表述数据组数

接下来T行,每行两个正整数,表示N, M

输出格式:

T行,每行一个整数表示第i组数据的结果

输入输出样例
输入样例#1:

2
10 10
100 100

输出样例#1:

30
2791

说明

T = 10000

N, M <= 10000000

题解

日常推式子。。。

p p 为素数,P表示素数集合:

ans=Pi=1nj=1m[gcd(i,j)=p] a n s = ∑ P ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ]

日常提出 p p

ans=Pi=1npj=1mp[gcd(i,j)=1]

日常替换 [gcd(i,j)=1] [ g c d ( i , j ) = 1 ]

ans=Pi=1npj=1mpd|gcd(i,j)μ(d) a n s = ∑ P ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ∑ d | g c d ( i , j ) μ ( d )

日常枚举 d d

ans=d|gcd(i,j)μ(d)Pi=1npj=1mp[d|gcd(i,j)]

日常枚举 d d 的倍数:

ans=Pd=1min(np,mp)μ(d)i=1ndpj=1mdp

ans=Pd=1min(np,mp)μ(d)ndpmdp a n s = ∑ P ∑ d = 1 m i n ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( d ) ⌊ n d p ⌋ ⌊ m d p ⌋

T=dp T = d p ,代入:

ans=Pd=1min(np,mp)μ(Tp)nTmT a n s = ∑ P ∑ d = 1 m i n ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( T p ) ⌊ n T ⌋ ⌊ m T ⌋

改为枚举 T T

ans=T=1min(n,m)p|Tμ(Tp)nTmT

f(T)=p|Tμ(Tp),T=i×p[j] f ( T ) = ∑ p | T μ ( T p ) , T = i × p [ j ] ,考虑线筛:

1.当 T T 本身为素数时,显然有f(T)=μ(1)=1

2.当 T T 拥有多个最小质因子(即i mod p[j]=0)时:

(1)当 i i 本身无多个相同质因子时,那么当且仅当我们枚举的素数等于p[j]时, μ(Tp) μ ( T p ) 的值不为 0 0 ,此时p=p[j],T=i×p[j],所以有 μ(Tp)=μ(i) μ ( T p ) = μ ( i )

(2)当 i i 本身就是拥有多个因子的数时,无论我们怎么枚举,μ(Tp)的值都为 0 0 ,此时,仍然有μ(Tp)=μ(i)

3.当 T T 的最小质因子只有一个时:

此时,T就比 i i 多了一个质因数p[j],因为有:

f(i)=p|iμ(ip)f(T)=p|Tμ(i×p[j]p) f ( i ) = ∑ p | i μ ( i p ) f ( T ) = ∑ p | T μ ( i × p [ j ] p )

因为 i i 中没有质因数p[j],所以有 μ(i×p[j]p)=μ(ip) μ ( i × p [ j ] p ) = − μ ( i p ) ,在此基础上, T T 还多了一个μ(i×p[j]p[j])=μ(i)。可得, f(T)=f(i)+μ(i) f ( T ) = − f ( i ) + μ ( i )

综上,我们得到线筛方程:

f(T)=μ(1)μ(i)f(i)+μ(i)TPi mod p[j]=0i mod p[j]0 f ( T ) = { μ ( 1 ) T ∈ P μ ( i ) i   m o d   p [ j ] = 0 − f ( i ) + μ ( i ) i   m o d   p [ j ] ≠ 0

再求一下 f(T) f ( T ) 的前缀和,利用下底分块,我们就可以 O(n) O ( n ) 解决询问了。

代码
#include<bits/stdc++.h>
#define R register int
using namespace std;
const int M=1e7+5,N=1e7;
int p[M],miu[M],f[M],T;
bool check[M];
void get()
{
    R i,j,t;
    check[1]=miu[1]=1;
    for(i=2;i<=N;++i)
    {
        if(!check[i])f[i]=1,miu[i]=-1,p[++p[0]]=i;
        for(j=1;j<=p[0];++j)
        {
            t=i*p[j];if(t>N)break;
            check[t]=1;
            if(i%p[j]==0){f[t]=miu[i];miu[t]=0;break;}
            miu[t]=-miu[i],f[t]=miu[i]-f[i];
        }
        f[i]+=f[i-1];
    }
}
long long ans;
void query(int n,int m)
{
    R l,r;ans=0;
    if(n>m)swap(n,m);
    for(l=1;l<=n;l=r+1)r=min(n/(n/l),m/(m/l)),ans+=1ll*(f[r]-f[l-1])*(n/l)*(m/l);
}
void in(){get();scanf("%d",&T);}
void ac()
{
    R i,a,b;
    for(i=1;i<=T;++i)
    scanf("%d%d",&a,&b),query(a,b),printf("%lld\n",ans);
}
int main()
{
    in();ac();
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值