NKOJ 3957 (BZOJ 2820)YY的GCD (莫比乌斯反演+线性筛)

P3957YY的GCD

问题描述

神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……

输入格式

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

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

输出格式

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

样例输入

2
10 10
100 100

样例输出

30
2791

提示

T = 10000

N, M <= 10000000


显然 Ans=min(n,m)pni=1mj=1[gcd(i,j)==p]p A n s = ∑ p m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) == p ] , p 为 质 数

f(p)=i=1nj=1m[gcd(i,j)==p],F(p)=i=1nj=1m[p|gcd(i,j)] 令 f ( p ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) == p ] , F ( p ) = ∑ i = 1 n ∑ j = 1 m [ p | g c d ( i , j ) ]

N=min(n,m)F(p)=p|kNf(k)=npmp 令 N = m i n ( n , m ) , 那 么 F ( p ) = ∑ p | k N f ( k ) = ⌊ n p ⌋ ⌊ m p ⌋

f(p)=p|kNμ(kp)F(k)=p|kNμ(kp)nkmk 反 演 一 下 , f ( p ) = ∑ p | k N μ ( k p ) F ( k ) = ∑ p | k N μ ( k p ) ⌊ n k ⌋ ⌊ m k ⌋

Ans=pNf(p)=pNp|kNμ(kp)nkmk 那 么 A n s = ∑ p N f ( p ) = ∑ p N ∑ p | k N μ ( k p ) ⌊ n k ⌋ ⌊ m k ⌋

如果是单组询问,到这里已经可以了,但本题有多组询问,因此
Ans=k=1Nnkmkp|kμ(kp)p 交 换 一 下 枚 举 顺 序 , A n s = ∑ k = 1 N ⌊ n k ⌋ ⌊ m k ⌋ ∑ p | k μ ( k p ) , p 为 质 数

后面的部分可以直接枚举质数再枚举倍数预处理,复杂度接近 O(n) O ( n )
但显然可以线性筛处理,令其为 g[i] g [ i ] ,当 p[j]|i p [ j ] | i 时, g[ip[j]]=μ(i) g [ i ∗ p [ j ] ] = μ ( i ) ,否则 g[ip[j]]=mu[i]g[i] g [ i ∗ p [ j ] ] = m u [ i ] − g [ i ]
然后分块处理即可,复杂度 O(n+Tn) O ( n + T n )


代码:

#include<stdio.h>
#include<algorithm>
#define N 10000005
#define ll long long
using namespace std;
ll T,P[N],tot,mu[N],g[N];
bool mark[N];
void EU()
{
    ll i,j;mu[1]=1;g[1]=0;
    for(i=2;i<N;i++)
    {
        if(!mark[i])P[++tot]=i,mu[i]=-1,g[i]=1;
        for(j=1;j<=tot&&i*P[j]<N;j++)
        if(i%P[j])mu[i*P[j]]=-mu[i],g[i*P[j]]=mu[i]-g[i],mark[i*P[j]]=1;
        else {mu[i*P[j]]=0;g[i*P[j]]=mu[i];mark[i*P[j]]=1;break;}
    }
    for(i=2;i<N;i++)g[i]+=g[i-1];
}
int main()
{
    ll n,m,i,j,ans;
    scanf("%lld",&T);EU();
    while(T--)
    {
        scanf("%lld%lld",&n,&m);ans=0;
        for(i=1;i<=n&&i<=m;i=j+1)
        {
            j=min(n/(n/i),m/(m/i));
            ans+=(n/i)*(m/i)*(g[j]-g[i-1]);
        }
        printf("%lld\n",ans);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值