题目描述
题解
题意:求满足
x2≡1(modn)
的x在[1,n]范围内的个数。
式子转化一下:
x2=kn+1
(x+1)(x−1)=kn
则
x+1=k1n1,x−1=k2n2
,其中
k1k2=k,n1n2=n
那么n1n2为n的约数。
我们根n的时间求出n的约数,枚举约数的倍数,求出x,然后判断x是否满足另外一个式子。
还有一个小技巧就是,可以光存储大于sqrtn的约数来枚举,这样比较省时间。
注意有可能有重复的解,需要hash来判重。
n=1为无解的情况,x=1为任意n>1的解,这一点很显然。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
const int max_n=1e5+5;
int n,x;
int a[max_n],ans[max_n];
map <int,bool> hash;
int main(){
scanf("%d",&n);
if (n==1){
printf("None.\n");
return 0;
}
ans[++ans[0]]=1;
for (int i=1;i*i<n;++i)
if (n%i==0) a[++a[0]]=n/i;
for (int i=1;i<=a[0];++i)
for (int j=a[i];j<=n;j+=a[i]){
x=j-1;
if ((x-1)%(n/a[i])==0&&!hash[x])
hash[x]=true,ans[++ans[0]]=x;
x=j+1;
if (j+1<=n&&(x+1)%(n/a[i])==0&&!hash[x])
hash[x]=true,ans[++ans[0]]=x;
}
sort(ans+1,ans+ans[0]+1);
for (int i=1;i<=ans[0];++i)
printf("%d\n",ans[i]);
}