NC232628. 数论只会Gcd
描述
int Gcd(int x, int y) { if(y == 0) return x; return Gcd(y, x % y); } void CoGcd(int m) { for(int i = 1; i <= m; i++) { for(int j = 1; j <= m; j++) { Gcd(i, j); } } }
给出m的值,进行t次询问,每次询问包含一对xi,yi。针对每次询问,输出整个程序执行过程当中,Gcd(xi, yi)被执行了多少次。
例如:m = 20,
Gcd(8,5)会被执行4次,对应的x, y值是
(8,5) (5,8) (13,8) (8,13),这4组x y,在调用Gcd时,会递归执行Gcd(8, 5)。
输入描述
第一行:2个数,t和m,中间用空格分割。(1 <= t <= 200, 10 <= m <= 1e9)
后面t行:每行2个数xi, yi,中间用空格分割。(1 <= xi, yi <= 1e9)
输出描述
输出共t行,对应t组询问的答案。
示例1
输入:
5 20 1 1 2 1 3 2 5 3 8 5
输出:
1 88 36 12 4
C++(clang++ 11.0.1) 解法, 执行用时: 477ms, 内存消耗: 16144K, 提交时间: 2022-09-06 13:06:44
#include<bits/stdc++.h> using namespace std; const int N=2e6+10; typedef long long ll; int gi() { int x=0,o=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') o=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*o; } int mu[N],smu[N],m; map<int,int> M; ll ans; int getsmu(int n) { if(n<N) return smu[n]; if(M.count(n)) return M[n]; int ret=1; for(int i=2,j;i<=n;i=j+1) { j=n/(n/i);ret-=(j-i+1)*getsmu(n/i); } return M[n]=ret; } ll cal(ll n,ll a,ll b,ll c) { if(n<0) return 0; if(!a) return (b/c)*(n+1); if(a>=c||b>=c) return cal(n,a%c,b%c,c)+n*(n+1)/2*(a/c)+(n+1)*(b/c); ll m=(a*n+b)/c; return n*m-cal(m-1,c,c-b-1,a); } ll cal(int x,int y,int n) { return cal(n/x-1,x,n%x,y); } int main() { mu[1]=1; for(int i=1;i<N;i++) for(int j=i+i;j<N;j+=i) mu[j]-=mu[i]; for(int i=1;i<N;i++) smu[i]=smu[i-1]+mu[i]; int T=gi();m=gi(); while(T--) { int x=gi(),y=gi(); if(x>m||y>m) cout<<"0\n"; else if(x<=y) cout<<"1\n"; else { y+=x; if(y>m) cout<<"2\n"; else { ans=4; for(int i=1,j;i<=m;i=j+1) { j=m/(m/i);ans+=4ll*(getsmu(j)-getsmu(i-1))*cal(x,y,m/i); } cout<<ans<<'\n'; } } } return 0; }