大爷的做法:因为
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√)
的。