欧拉函数例(Codeforces 1295D Same GCDs)

10 篇文章 0 订阅
1 篇文章 0 订阅

欧拉函数系列

题意:

  • 给定两个数 a , m ( m > a ) a, m(m>a) a,m(m>a), 求 [ 0 , m − 1 ] [0, m-1] [0,m1]中有多少个整数使得 g c d ( a , m ) = g c d ( a + x , m ) gcd(a, m) = gcd(a + x, m) gcd(a,m)=gcd(a+x,m)

数据范围: 1 ≤ a < m ≤ 1 0 10 1\leq a<m\leq 10^{10} 1a<m1010

Tutorial:

根据gcd的性质有 g c d ( a , b ) = g c d ( a % b , b ) gcd(a, b) = gcd(a\%b, b) gcd(a,b)=gcd(a%b,b), 于是乎 g c d ( a , m ) = g c d ( a + x , m ) = g c d ( ( a + x ) % m , m ) gcd(a, m) = gcd(a+x, m)=gcd((a+x)\%m, m) gcd(a,m)=gcd(a+x,m)=gcd((a+x)%m,m), 然后结合 x x x的范围观察 ( a + x ) % m (a+x)\%m (a+x)%m, 发现或者就是m的一个轮回, 相当于直接找到 g c d ( a , m ) = g c d ( x , m ) gcd(a, m) = gcd(x, m) gcd(a,m)=gcd(x,m)的x的个数,然后 0 ≤ x < m 0\leq x<m 0x<m,发现答案等于 Φ ( m g c d ( a , m ) ) \Phi(\frac{m}{gcd(a, m)}) Φ(gcd(a,m)m)


#include <bits/stdc++.h>
#include <bits/extc++.h>

using namespace std;
#define _rep(n, a, b) for (ll n = (a); n <= (b); ++n)
#define _rev(n, a, b) for (ll n = (a); n >= (b); --n)
#define _for(n, a, b) for (ll n = (a); n < (b); ++n)
#define _rof(n, a, b) for (ll n = (a); n > (b); --n)
#define oo 0x3f3f3f3f3f3f
#define ll long long
#define db double
#define eps 1e-8
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl
#define met(a, b) memset(a, b, sizeof(a))
#define all(x) x.begin(), x.end()
#define pii pair<ll, ll>
const ll mod = 1e9 + 7;
const ll maxn = 1e5 + 5;
ll euler(ll n)
{
	ll ret = n;
	for (ll i = 2; i * i <= n; i++)
	{
		if (n % i == 0)
		{
			ret = ret / i * (i - 1);
			while (n % i == 0)
				n /= i;
		}
	}
	if (n > 1)
		ret = ret / n * (n - 1);
	return ret;
}
ll E[maxn];
void euler()
{
	for (int i = 2; i < maxn; i++)
	{
		if (!E[i])
			for (int j = i; j < maxn; j += i)
			{
				if (!E[j])
					E[j] = j;
				E[j] = E[j] / i * (i - 1);
			}
	}
}

signed main()
{
	int t;
	cin >> t;
	_rep(cas, 1, t)
	{
		ll a, m;
		cin >> a >> m;
		ll g = __gcd(a, m);
		cout << euler(m/g) << endl;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值