题面:
题意:
给定两个整数
a
a
a,
m
m
m。
询问满足
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) 且
0
≤
x
<
m
0\le x<m
0≤x<m 的不同
x
x
x 的个数。
题解:
我们设
g
=
g
c
d
(
a
,
m
)
g=gcd(a,m)
g=gcd(a,m),那么我们有
g
c
d
(
k
1
∗
g
+
x
,
k
2
∗
g
)
=
g
gcd(k1*g+x,k2*g)=g
gcd(k1∗g+x,k2∗g)=g,即
x
=
k
3
∗
g
x=k3*g
x=k3∗g 且
0
≤
k
3
∗
g
<
m
0\le k3*g<m
0≤k3∗g<m ,
0
≤
k
3
<
m
/
g
=
k
2
0\le k3<m/g=k2
0≤k3<m/g=k2
g c d ( k 1 ∗ g + k 3 ∗ g , k 2 ∗ g ) = g gcd(k1*g+k3*g,k2*g)=g gcd(k1∗g+k3∗g,k2∗g)=g ,有 g c d ( k 1 + k 3 , k 2 ) = 1 gcd(k1+k3,k2)=1 gcd(k1+k3,k2)=1, k 1 > = 1 k1>=1 k1>=1。
g c d ( k 1 + k 3 , k 2 ) = 1 gcd(k1+k3,k2)=1 gcd(k1+k3,k2)=1 等价于 g c d ( ( k 1 + k 3 ) m o d k 2 , k 2 ) = 1 gcd((k1+k3)\ mod\ k2,k2)=1 gcd((k1+k3) mod k2,k2)=1,又 k 3 ∈ [ 0 , k 2 ] k3\in[0,k2] k3∈[0,k2]。
实际上就是求 [ 1 , k 2 ] [1,k2] [1,k2] 中有多少个数与 k 2 k2 k2 互质。
很明显欧拉函数求解即可。
我们还可以用容斥来求。
我们将 k 2 k2 k2 的因子从小到大排序,排序后,其因子的关系形成一张 D A G DAG DAG。
我们设 c n t [ i ] cnt[i] cnt[i] 为 [ 1 , k 2 ] [1,k2] [1,k2] 中的数 与 k 2 k2 k2 的 g c d gcd gcd 为 k 2 k2 k2 第 i i i 个因子的数的个数。
初始化时,我们将 c n t [ i ] cnt[i] cnt[i] 初始化为 [ 1 , k 2 ] [1,k2] [1,k2] 中的数 与 k 2 k2 k2 的 g c d gcd gcd 大于等于 k 2 k2 k2 第 i i i 个因子的数的个数。
那么 c n t [ 1 ] cnt[1] cnt[1] 即为所求 g c d = 1 gcd=1 gcd=1
那么很容易得到一个 O ( s u m ( f a c ) 2 ) O(sum(fac)^2) O(sum(fac)2) 的容斥算法。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<ctime>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const double alpha=0.75;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int maxp=100100;
const int up=1100;
ll fac[maxn],cnt[maxn],tot=0;
ll gcd(ll a,ll b)
{
if(b==0) return a;
return gcd(b,a%b);
}
void gao(ll n)
{
tot=0;
for(ll i=1;i*i<=n;i++)
{
if(n%i) continue;
fac[++tot]=i;
if(i*i!=n) fac[++tot]=n/i;
}
}
int main(void)
{
int tt;
scanf("%d",&tt);
while(tt--)
{
ll a,m;
scanf("%lld%lld",&a,&m);
ll g=gcd(a,m);
a/=g,m/=g;
gao(m);
sort(fac+1,fac+tot+1);
for(int i=1;i<=tot;i++)
cnt[i]=m/fac[i];
for(int i=tot;i>=1;i--)
{
for(int j=i+1;j<=tot;j++)
if(fac[j]%fac[i]==0)
cnt[i]-=cnt[j];
}
printf("%lld\n",cnt[1]);
}
return 0;
}