列表

详情


NC232628. 数论只会Gcd

描述

有这样一段两两求最大公约数的程序CoGcd,
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;
}

上一题