Educational Codeforces Round 81 D-Same GCDs(欧拉函数)

题面

给定两个数a和m,在 [ 0 , m ) [0,m) 内寻找有多少个x使 g c d ( a , m ) = g c d ( a + x , m ) gcd(a,m)=gcd(a+x,m)
1<=a<m<=1010

分析

询问了队友后得到了正确的建模思路。。。

可以先把问题简化,通过gcd(a,m)化简一波: g c d ( a / g c d ( a , m ) , m / g c d ( a , m ) ) = 1 gcd(a/gcd(a,m),m/gcd(a,m))=1
为表达简单,使 a = a / g c d ( a , m ) , m = m / g c d ( a , m ) a=a/gcd(a,m),m=m/gcd(a,m)

注意到此时问题变成了一个互质问题
[ 0 , m ) [0,m) 内寻找有多少个x使 1 = g c d ( a + x , m ) 1=gcd( a + x, m)
(x的范围可能缩小了,但是删去的部分肯定不是答案,因为那部分x包含a和m的公因子,不能使 g c d ( a + x , m ) = 1 gcd(a+x,m)=1

联想到欧几里得算法,可以将后面的部分化到最简:当a+x大于等于m时, g c d ( a + x , m ) = g c d ( ( a + x ) m , m ) gcd(a+x,m)=gcd((a+x)-m,m)
分类:
a+x<m时, g c d ( a + x , m ) gcd(a+x,m) ,其中 a + x [ a , m ) a+x∈[a,m)
a+x>=m时, g c d ( a + x , m ) = g c d ( a + x m , m ) gcd(a+x,m)=gcd(a+x-m,m) ,其中 a + x m [ 0 , a ) a+x-m∈[0,a)

由此,问题变成求 [ 0 , m ) [0,m) 内与m互质数的个数,即欧拉函数φ(m)

代码

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
ll gcd(ll a, ll b)
{
	if (b == 0)return a;
	return gcd(b, a % b);
}
int main()
{
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	ll a, m,fai=1,g;
	for (int o = 0; o < t; o++)
	{
		cin >> a >> m;
		g = gcd(a, m);
		m /= g;
		//求m/gcd(a,m)的欧拉函数
		fai = m;
		for (ll i = 2; i*i <= m; i++)
		{
			if (m % i == 0) {
				fai = fai / i * (i - 1);
				while (m % i == 0)m /= i;
			}
		}
		if (m > 1)fai = fai / m * (m - 1);
		cout << fai << endl;
	}
	return 0;
}
发布了4 篇原创文章 · 获赞 0 · 访问量 47

猜你喜欢

转载自blog.csdn.net/engineoid/article/details/104113874
今日推荐