题目
给定(n(nleq 2*10^9)),求
[sum_{x=1}^n[x^2mod n==1]
]
分析
首先当(n=1)的时候需要特判,
否则1和(n-1)一定是答案,
那么对于一个(x=x'+1)来说,也满足
((x'+1)^2mod n==1)
把这个式子拆开可以得到
(x'(x'+2)mod n==0)
那么考虑枚举(n)中(geqsqrt{n})的约数,
那么(x')或者(x'+2)一定是这个数的倍数,
再枚举这个约数的倍数判断是否满足上式即可,
再通过(x')就可以推出(x)了
PS:为什么不直接枚举(n)的约数?
因为(<sqrt{n})的约数所对应的另一个数也就是(>sqrt{n})的约数
当枚举(geqsqrt{n})的约数的倍数,
如果满足上式也就说明
(x',x'+2)的另一个数就是(leqsqrt{n})的约数的倍数
而枚举(leqsqrt{n})的倍数显然会T飞,
那还不如只枚举(geqsqrt{n})的约数的倍数,
时间复杂度不会证,也许是(O(sqrt{n}log{n}))吧
代码
#include <cstdio>
#include <algorithm>
#define rr register
using namespace std;
int n,m,a[100011];
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed main(){
scanf("%d",&n),a[1]=1,a[m=2]=n-1;
if (n==1) return !printf("None");
for (rr int i=2;i*i<=n;++i)
if (n%i==0){
for (rr int j=n/i;j<n;j+=n/i){
if (1ll*j*(j+2)%n==0) a[++m]=j+1;
if (1ll*j*(j-2)%n==0) a[++m]=j-1;
}
}
sort(a+1,a+1+m),m=unique(a+1,a+1+m)-a-1;
for (rr int i=1;i<=m;++i) print(a[i]),putchar(10);
return 0;
}