大爷的做法:因为x2≡1(modn),不妨设n=pq,则p|(x+1),q|(x−1),所以枚举大的那个,就是T(d(n)∗n√)≈T(n/10)
傻逼的做法:
考虑crt,设n=pk,k≥1,p为质数。
若p>2,
因为(x+1,x-1)≤(x+1)-(x-1)=2,所以要么pk|x+1,要么pk|x−1。
若pk|x+1,则x=pk−1=n−1;
若pk|x−1,则x=1.
若p=2,
显然1与pk−1依然可以。
若(x-1,x+1)=1,则显然与上面同样。
那么不妨设x+1=2a,x-1=2b,(a,b)=1,若2k|4a,则2k−2|a.所以,要么x+1=2k−1,要么x−1=2k−1。
代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int prime[44728];
bool p[44728];
int a[10],ans[1000005];
long long n;
void gcd(int a,int b,int &x,int &y){
if(b){
gcd(b,a%b,y,x);
y-=a/b*x;
}
else x=1,y=0;
}
void dfs(int x,long long now){
if(x<0){
ans[++ans[0]]=now;
return;
}
int y1,y2;
gcd(n/a[x],a[x],y1,y2);
/*cout<<"---"<<x<<","<<now<<"---\n";
printf("%d\n",(int)(y1*n/a[x]+y2*a[x]));*/
if(a[x]>2&&(~a[x]&1)){
dfs(x-1,((now+((a[x]>>1)-1)*n/a[x]%n*y1)%n+n)%n);
dfs(x-1,((now+((a[x]>>1)+1)*n/a[x]%n*y1)%n+n)%n);
}
dfs(x-1,((now+n/a[x]*y1)%n+n)%n);
dfs(x-1,((now+(a[x]-1)*n/a[x]%n*y1)%n+n)%n);
}
int main(){
int i,j,L;
scanf("%lld",&n);
if(n==1){
puts("None");
return 0;
}
L=sqrt(n);
for(i=2;i<=L;++i){
if(!p[i])prime[++prime[0]]=i;
for(j=1;j<=prime[0]&&i*prime[j]<=L;++j){
p[i*prime[j]]=1;
if(!(i%prime[j]))break;
}
}
int tot=0,tmp=n;
for(i=prime[0];i;--i)
if(!(tmp%prime[i])){
a[tot]=1;
for(;!(tmp%prime[i]);tmp/=prime[i])a[tot]*=prime[i];
++tot;
}
if(tmp!=1)a[tot++]=tmp;
dfs(tot-1,0);
sort(ans+1,ans+ans[0]+1);
ans[0]=unique(ans+1,ans+ans[0]+1)-ans-1;
for(i=1;i<=ans[0];++i)printf("%d\n",ans[i]);
}
总结:
①一定要仔细读题,找出特殊数据。
②若n=p*q,且p、q等价,则小的那个是O(n√)的。