[洛谷P2257] YY的GCD

it2025-02-27  35

Description

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

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

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

多组输入

Input

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

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

Output

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

Sample Input

2 10 10 100 100

Sample Output

30 2791

HINT

T = 10000 N, M <= 10000000


想法

Orz PoPoQQQ大神…… 若枚举每个质数 \(p\)\[ \begin{equation*} \begin{aligned} ans&= \sum\limits_p \sum\limits_{p|k} \mu(\frac{k}{p}) F(k) \\ &= \sum\limits_p \sum\limits_{d=1}^{\frac{min(n,m)}{p}} \mu(d) \lfloor \frac{n}{dp} \rfloor \lfloor \frac{m}{dp} \rfloor \end{aligned} \end{equation*} \]\(T=dp\)\[ ans=\sum\limits_{T=2}^{min(n,m)} \lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor \sum\limits_{p|T 且p为质数} \mu(\frac{T}{p}) \] 预处理计算每个数 \(T\)\(\sum\limits_{p|T 且p为质数} \mu(\frac{T}{p})\) 及其前缀和 用每个质数把自己的倍数筛一遍就行了。


代码

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N = 10000005; int mu[N]; ll sum[N]; int prime[N],pnum,p[N]; int getmu(){ mu[1]=1; for(int i=2;i<N;i++) p[i]=1; for(int i=2;i<N;i++){ if(p[i]) { prime[pnum++]=i; mu[i]=-1; } for(int j=0;j<pnum && (ll)prime[j]*i<N;j++){ p[i*prime[j]]=0; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } for(int i=0;i<pnum;i++) for(int j=1;(ll)j*prime[i]<N;j++) sum[j*prime[i]]+=mu[j]; sum[1]=0; for(int i=2;i<N;i++) sum[i]+=sum[i-1]; } int n,m,T; int main() { getmu(); scanf("%d",&T); ll ans; while(T--){ scanf("%d%d",&n,&m); ans=0; for(int l=2,r;l<=min(n,m);l=r+1){ r=min(n/(n/l),m/(m/l)); ans+=(sum[r]-sum[l-1])*(n/l)*(m/l); } printf("%lld\n",ans); } return 0; }

转载于:https://www.cnblogs.com/lindalee/p/8504303.html

相关资源:数据结构—成绩单生成器
最新回复(0)