Codeforces 1295 D. Same GCDs

落花浮王杯 提交于 2020-02-05 04:46:47

Codeforces 1295 D. Same GCDs

题意:

给定两个整数\(a,m\leq10^{10}\)

问有多少个\(0\leq x<m\)\(gcd(a,m)=gcd(a+x,m)\)

思路:

把结果写成表达式
\[ \sum_{x=0}^{m-1}[gcd(a,m)=gcd(a+x,m)] \]
根据gcd的计算过程有:
\[ \sum_{x=0}^{m-1}[gcd(a,m)=gcd((a+x)mod\ m,\ m)] \]
我们知道\(x\)的取值范围在\([0,m-1]\),其实就是相当于把\(a\)在数轴上向右平移了这么多个单位,取模之后又回到了\([0,m-1]\)的区间。

所以有
\[ \sum_{i=0}^{m-1}[gcd(i,m)=gcd(a,m)] \]
提取\(gcd(a,m)=d\)
\[ \sum_{i=0}^{m-1}[gcd(i,m)=g]\\\sum_{0\leq i<m}^{g|i}[gcd(\frac{i}{g},\frac{m}{g})=1] \]
这个就是\(\varphi(\frac{m}{g})\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, m;
ll phi(ll x)
{
    ll res = x;
    for(ll i = 2; i <= x/i; i++)
    {
        if(x % i == 0)
        {
            res = res/i*(i-1);
            while(x%i == 0) x /= i;
        }
    }
    if(x > 1) res = res/x*(x-1);
    return res;
}

ll gcd(ll a, ll b){
    if(b == 0) return a;
    return gcd(b, a%b);
}

void solve()
{
    cin >> a >> m;
    ll k = gcd(a, m);
    cout << phi(m/k) << endl;
}

int main()
{
    int T; scanf("%d", &T);
    while(T--) solve();
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!