题目大意
给你一个
n
n
,求最小正整数,使得对于任意整数
a
a
都满足
或输出无解。
做法
首先发现
n
n
含有平方因子时是无解的。
假设含有平方因子
pc
p
c
,那么我们令
a=npcp
a
=
n
p
c
p
时是不合法的。
因为
nk≥n≥2c≥c
n
k
≥
n
≥
2
c
≥
c
,因此
ank
a
n
k
显然模
n
n
为0,而显然模
n
n
不为。
考虑中国剩余定理,因此对于
n
n
每个质因子都要有
ank≡a(mod p)
a
n
k
≡
a
(
m
o
d
p
)
a
a
是的倍数显然成立,这里只考虑
(a,p)=1
(
a
,
p
)
=
1
。
ank−1≡1(mod p)
a
n
k
−
1
≡
1
(
m
o
d
p
)
接下来我们可以证明
p−1|nk−1
p
−
1
|
n
k
−
1
。
因为
p
p
是质数,一定存在原根。
如果
a=g
a
=
g
,显然
p−1|nk−1
p
−
1
|
n
k
−
1
。
否则设
a=gc
a
=
g
c
,显然
c
c
不为。有
c(nk−1)≡0(mod p−1)
c
(
n
k
−
1
)
≡
0
(
m
o
d
p
−
1
)
显然也有
p−1|nk−1
p
−
1
|
n
k
−
1
。
因此我们现在求出所有
p−1
p
−
1
的最小公倍数,记为
lcm
l
c
m
,那么
lcm|nk−1
l
c
m
|
n
k
−
1
。
因此
nk≡1(mod lcm)
n
k
≡
1
(
m
o
d
l
c
m
)
。
如果
(n,lcm)
(
n
,
l
c
m
)
不为
1
1
显然无解,否则肯定有解,因为就是可行解。
将
ϕ(lcm)
ϕ
(
l
c
m
)
分解质因数,枚举一个质因数并代入检验,即可得到最小
k
k
<script type="math/tex" id="MathJax-Element-3288">k</script>。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll p[1000];
int c[1000];
ll n,phi,k;
int i,tot,top;
ll random(ll x){
ll t=rand()%10000;
t=t*10000+rand()%10000;
t=t*10000+rand()%10000;
t=t*10000+rand()%10000;
return t%x;
}
ll mul(ll a,ll b,ll p){
ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
return tmp<0?tmp+p:(tmp>=p?tmp-p:tmp);
}
ll qsm(ll x,ll y,ll mo){
if (!y) return 1;
ll t=qsm(x,y/2,mo);
t=mul(t,t,mo);
if (y%2) t=mul(t,x,mo);
return t;
}
bool Miller_Rabin(ll n){
if (n==1) return 0;
int s=10,t=0,i;
ll a,p,k=n-1;
while (k%2==0) k/=2,t++;
while (s--){
a=random(n-1)+1;
p=a=qsm(a,k,n);
fo(i,1,t){
a=mul(a,a,n);
if (a==1&&p!=1&&p!=n-1) return 0;
p=a;
}
if (a!=1) return 0;
}
return 1;
}
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll Pollard_Rho(ll n){
ll k,x,y,c,d,i=1;
while (1){
c=random(n-1);
k=2;y=x=random(n);
i=1;
while (1){
y=(mul(y,y,n)+c)%n;
d=gcd(abs(x-y),n);
if (i==k) x=y,k<<=1;
i++;
if (d!=1) break;
}
if (d!=n) return d;
}
}
void work(ll n){
if (Miller_Rabin(n)){
p[++top]=n;
return;
}
ll p=Pollard_Rho(n);
ll q=n/p;
work(p);work(q);
}
void dfs(int x,ll y){
if (y>=k) return;
if (x==top+1){
ll t=qsm(n,y,phi);
(t+=phi)%=phi;
if (t==1) k=y;
return;
}
int i;
ll t=1;
fo(i,0,c[x]){
dfs(x+1,y*t);
t=t*p[x];
}
}
int main(){
freopen("pow.in","r",stdin);freopen("pow.out","w",stdout);
scanf("%lld",&n);
work(n);
sort(p+1,p+top+1);
phi=1;
fo(i,1,top){
phi=phi*(p[i]-1)/gcd(phi,p[i]-1);
if (p[i]==p[i-1]){
printf("-1\n");
return 0;
}
}
if (gcd(phi,n)!=1){
printf("-1\n");
return 0;
}
if (phi==1){
printf("1\n");
return 0;
}
top=0;
work(phi);
sort(p+1,p+top+1);
k=1;
fo(i,1,top){
if (p[i]==p[i-1]) k=k*p[i];
else k=k*(p[i]-1);
}
if (k==1){
printf("1\n");
return 0;
}
top=0;
work(k);
sort(p+1,p+top+1);
tot=top;
top=0;
fo(i,1,tot){
if (p[i]!=p[i-1]){
top++;
p[top]=p[i];
c[top]=1;
}
else c[top]++;
}
dfs(1,1);
printf("%lld\n",k);
}