Same GCDs 欧拉函数

在这里插入图片描述
∑ x = 0 m − 1 [ g c d ( a , m ) = g c d ( a + x , m ) ] \sum_{x=0}^{m-1}[gcd(a,m)=gcd(a+x,m)] x=0m1[gcd(a,m)=gcd(a+x,m)]
g c d ( a , m ) = g c d ( a + 0 , m ) , g c d ( a , m ) = g c d ( a + m , m ) gcd(a,m)=gcd(a+0,m),gcd(a,m)=gcd(a+m,m) gcd(a,m)=gcd(a+0,m),gcd(a,m)=gcd(a+m,m)
所以原式: = ∑ x = 1 m [ g c d ( a + x , m ) = g c d ( a , m ) ] =\sum_{x=1}^{m}[gcd(a+x,m)=gcd(a,m)] =x=1m[gcd(a+x,m)=gcd(a,m)] = ∑ k = a + 1 m + a [ g c d ( k , m ) = g c d ( a , m ) ] =\sum_{k=a+1}^{m+a}[gcd(k,m)=gcd(a,m)] =k=a+1m+a[gcd(k,m)=gcd(a,m)]
g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b)=gcd(b,a\%b) gcd(a,b)=gcd(b,a%b),可知 [ 1 , m ] [1,m] [1,m]中的结果会与 [ a + 1 , a + m ] [a+1,a+m] [a+1,a+m]中的结果一一对应起来。
因此有 = ∑ k = 1 m [ g c d ( k , m ) = g c d ( a , m ) ] =\sum_{k=1}^{m}[gcd(k,m)=gcd(a,m)] =k=1m[gcd(k,m)=gcd(a,m)]
g = g c d ( a , m ) g=gcd(a,m) g=gcd(a,m),
= ∑ k = 1 m g [ ( k , m g ) = 1 ] = φ ( m g ) =\sum_{k=1}^{\frac{m}{g}}[(k,\frac{m}{g})=1]=\varphi(\frac{m}{g}) =k=1gm[(k,gm)=1]=φ(gm)

质因子分解后求个欧拉函数即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

#define ll long long

const int N = 1e6+10;
ll p[N], prime[N], m;
ll index[N], tot;
void primes(ll n){
	for(ll i = 2; i <= n; i++){
		if(!p[i]) p[i] = i, prime[++m] = i;
		for(ll j = 1; j <= m; j++){
			if(prime[j] > p[i] || prime[j] > n/i) break;
			p[i*prime[j]] = prime[j];
		}
	}

	//for(ll i = 1; i <= 100; i++) cout << prime[i] << endl;
}

void fac_div(ll n){
	tot = 0;
	for(ll i = 1; i <= m && prime[i]*prime[i] <= n; i++){
		if(n%prime[i] == 0){
			index[++tot] = prime[i];
			while(n%prime[i]==0) n/=prime[i]; 
		}
		if(n==1) break;
	} 
	if(n>1) index[++tot] = n;
}

ll phi(ll n){
	fac_div(n);
	ll ans = n;
	for(int i = 1; i <= tot; i++){
		ans = ans/index[i]*(index[i]-1);
	}
	return ans;
}
int main(){
	primes(1e6);
	int t;
	scanf("%d", &t);
//	for(ll i = 1; i <= 20; i++) cout << phi(i) << endl;
	while(t--){
		ll a, n, ans = 0;
		scanf("%lld%lld", &a, &n);
		ans = phi(n/__gcd(a,n));
		printf("%lld\n", ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值