题目大意:
给定正整数 n n ,求最小的正整数满足对于任意正整数 a a ,,无解则输出-1。 n≤1018 n ≤ 10 18
解题思路:
首先如果
n
n
有平方因子,那么令
a=p
a
=
p
,则
pnkmodn
p
n
k
mod
n
一定是
p2
p
2
的倍数,所以无解。
否则根据CRT得到
n
n
的质因子个同余方程:
若
p=2
p
=
2
则一定成立,否则有
nk≡1(modp−1)
n
k
≡
1
(
mod
p
−
1
)
。首先要满足
n,p−1
n
,
p
−
1
互质,然后类似于求原根,根据欧拉定理,得知
k
k
一定为的因数。
由于如果
nx≠1
n
x
≠
1
,那么
x
x
的因数肯定也不行,所以求出我们不用枚举因数,用试除法即可。
最后的答案为所有 k k <script type="math/tex" id="MathJax-Element-1568">k</script>的lcm。
#include<iostream>
#include<algorithm>
#include<map>
#define ll long long
#define LL __int128
using namespace std;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll Pow(ll x,ll y,ll mod)
{
x%=mod;ll res=1;
for(;y;y>>=1,x=(LL)x*x%mod)
if(y&1)res=(LL)res*x%mod;
return res;
}
bool check(ll x,ll n,ll r,ll s)
{
x=Pow(x,r,n);ll pre=x;
for(int i=1;i<=s;i++)
{
x=(LL)x*x%n;
if(x==1&&pre!=1&&pre!=n-1)return false;
pre=x;
}
return x==1;
}
bool MR(ll n)
{
if(n<2)return false;
if(n==2)return true;
if(!(n&1))return false;
ll r=n-1,s=0;
while(!(r&1))r>>=1,s++;
for(int i=0;i<9;i++)if(!check(rand()%(n-1)+1,n,r,s))return false;
return true;
}
ll rho(ll n,ll c)
{
ll x=rand()%n,y=x,k=2,p=1;
for(int i=1;p==1;i++)
{
x=((LL)x*x+c)%n;
p=x>y?x-y:y-x;
p=gcd(p,n);
if(i==k)y=x,k<<=1;
}
return p;
}
void div(map<ll,int>&D,ll n)
{
if(n==1)return;
if(MR(n)){D[n]++;return;}
ll t=n;
while(t==n)t=rho(n,rand()%(n-1)+1);
div(D,n/t),div(D,t);
}
ll Phi(ll n)
{
ll res=n;
map<ll,int>D;div(D,n);
for(auto &v:D)res=res/v.first*(v.first-1);
return res;
}
ll solve(ll n,ll p)
{
if(gcd(n,p)!=1){puts("-1");exit(0);}
ll res=Phi(p);
map<ll,int>D;div(D,res);
for(auto &v:D)
for(int i=1;i<=v.second;res/=v.first,i++)
if(Pow(n,res/v.first,p)!=1)break;
return res;
}
int main()
{
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);
ll n;map<ll,int>D;
cin>>n;div(D,n);
ll ans=1;
for(auto &v:D)
{
if(v.second>1){puts("-1");return 0;}
if(v.first!=2)ans=lcm(ans,solve(n,v.first-1));
}
cout<<ans<<'\n';
return 0;
}