题意:
给定一个 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;
}