Codeforces 1295D Same GCDs(欧拉函数)

传送门

题意:给定a,m\le10^{10},若0\le x<m,求有多少个x满足gcd(a,m)==gcd(a+x,m)

题解:如果满足gcd相同则x必须为gcd(a,m)的倍数,设gcd(a,m)=d,a=ud,m=vd,则若0\le w<v,有多个w满足gcd(u+w,v)==1。因为d是最大公因数所以gcd(u,v)==1。到这里(凭借丰富的骗分经验?)就可以直接猜一波答案是phi(v)了。所以求个gcd再求个欧拉函数就完事儿。一开始欧拉函数没写好还T了一发......这次真的是自己把答案猜对的(*—*)

下面证明一下答案:

相当于要证正整数序列上每个长度为v的周期内与v互质的数的个数相等并且它们的分布是和第一个周期[1, v]是相同的。即证gcd(kx+a,x)==1\Leftrightarrow gcd(a,x)==1,然后充分性和必要性都反证一下就好了。

为什么证明了与v互质的数的分布的周期性就好?因为有了周期性后,可以把询问的区间进行平移。最后gcd(u+w,v)==10\le w<v就可以转化为gcd(x,v)==11\le x \le v

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a,m;
inline ll read() {
	ll x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x*f;
}
inline ll gcd(ll a,ll b) {
	return !b?a:gcd(b,a%b);
}
inline ll phi(ll x) {
	ll ret=1;
	for (register ll i=2;i*i<=x;++i)
		if (x%i==0) {
			ll cur=1;
			while (x%i==0) {
				cur*=i;
				x/=i;
			}
			ret*=(i-1)*cur/i;
		}
	if (x>1) ret*=x-1;
	return ret;
}
int main() {
	int kase=read();
	while (kase--) {
		a=read(),m=read();
		ll v=m/gcd(a,m);
		printf("%lld\n",phi(v));
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值