题意:
给定一个 n n n,求出所有 1 1 1到 n n n之间的 x x x,使得 x 2 = 1 ( m o d n ) x^2=1\ (mod\ n) x2=1 (mod n)
分析:
很妙的思维
先把原式变为
(
x
+
1
)
∗
(
x
−
1
)
=
k
∗
n
(
k
ϵ
Z
)
(x+1)*(x-1)=k*n(k\ \epsilon\ \mathbb{Z})
(x+1)∗(x−1)=k∗n(k ϵ Z)
假设
a
∗
b
=
n
a*b=n
a∗b=n且
a
∣
x
+
1
,
b
∣
x
−
1
a|x+1,b|x-1
a∣x+1,b∣x−1,当然
a
,
b
a,b
a,b的位置是可以互换的
如果可以满足这样的条件,
x
=
k
∗
b
+
1
x=k*b+1
x=k∗b+1必定是合法的
所以我们可以枚举
a
a
a,这样可以算出
b
b
b,再通过枚举
k
k
k,算出
x
x
x
然后将
x
x
x代入
x
+
1
x+1
x+1中看是否能被
a
a
a整除
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
inline LL read()
{
LL s=0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
return s*f;
}
LL ans[2000005],len=0;
int main()
{
LL n=read();ans[++len]=1;
for(LL i=1;i*i<=n;i++)
{
if(n%i) continue;
LL a=i,b=n/i;
for(LL j=1;j*b+1<=n;j++) if(!((j*b+2)%a)) ans[++len]=j*b+1;
for(LL j=1;j*b-1<=n;j++) if(!((j*b-2)%a)) ans[++len]=j*b-1;
}
sort(ans+1,ans+1+len);
len=unique(ans+1,ans+1+len)-ans-1;
for(LL i=1;i<=len;i++) printf("%lld\n",ans[i]);
return 0;
}