Same GCDs(CodeForces - 1295D )

传送飞船

You are given two integers aa and mm. Calculate the number of integers xx such that 0≤x<m0≤x<m and gcd(a,m)=gcd(a+x,m)gcd(a,m)=gcd(a+x,m).

Note: gcd(a,b)gcd(a,b) is the greatest common divisor of aa and bb.

Input

The first line contains the single integer TT (1≤T≤501≤T≤50) — the number of test cases.

Next TT lines contain test cases — one per line. Each line contains two integers aa and mm (1≤a<m≤10101≤a<m≤1010).

Output

Print TT integers — one per test case. For each test case print the number of appropriate xx-s.

Example

Input

3
4 9
5 10
42 9999999967

Output

6
1
9999999966

Note

In the first test case appropriate xx-s are [0,1,3,4,6,7][0,1,3,4,6,7].

In the second test case the only appropriate xx is 00.

 

题意:T组输入,整数a和m,求有多少个x(0≤ x <m)满足 gcd(a,m) = gcd(a+x,m),gcd(a,m)时a和m的最大公因数。

题解:设k = a+x,则a≤ k <a+m;可将其拆分为[a,m],[m+1,m+a)。(超重要!)根据gcd(a,b)的原理:gcd(a,b) = gcd(b,a%b)——k∈[1,a)与k∈[m+1,m+a)的gcd个数应该相等。即k∈[1,m],求gcd(k,m) == gcd(a,m)的个数。等同于求m/gcd(a,m)的欧拉函数。

 

欧拉欧拉欧拉欧拉!一个求1到n中与n互质的个数的函数。

ll euler(ll n){
	ll ans = n;
	for(ll i=2; i*i<=n; i++)
		if(n%i == 0){
			ans = ans/i*(i-1);//res - res/i;这样做是为了防止中间数据溢出 
			while(n%i == 0)	n /= i;
		}
	if(n > 1)	ans = ans/n*(n-1);
	return ans;
}

最重要的是利用gcd的原理将题目转化,然后利用欧拉函数求解,代码比较简单,没什么可解读的了。

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e10+50;

ll gcd(ll a, ll b){	return b? gcd(b, a%b): a;}
ll euler(ll n){
	ll ans = n;
	for(ll i=2; i*i<=n; i++)
		if(n%i == 0){
			ans = ans/i*(i-1);//res - res/i;这样做是为了防止中间数据溢出 
			while(n%i == 0)	n /= i;
		}
	if(n > 1)	ans = ans/n*(n-1);
	return ans;
}

int t;
int main(){
	scanf("%d", &t);
	while(t--){
		ll a, b;
		scanf("%lld%lld", &a, &b);
		b /= gcd(a, b);
		printf("%lld\n", euler(b));
	}
	return 0;
}

 

 
展开阅读全文
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值