题目大意:求0<=x<n 且 x^x=1(mod n)
容易化成x^2-ny=1; 设 n=n1*n2 y=y1*y2
n1*n2*y1*y2=(x+1)(x-1)
设n1*y1=x+1 n2*y2=x-1
相减得n1*y1-n2*y2=2
然后扩展欧几里得直接上就可以了。
这样求的答案可能有重复,用set搞一搞。
code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<set>
#include<cmath>
#define LL long long
using namespace std;
set<LL> q;
int n;
int exgcd(int a,int b,LL &x,LL &y)
{
if(a==0){x=0;y=1;return b;}
LL tx,ty;int d=exgcd(b%a,a,tx,ty);
y=tx;x=ty-(b/a)*tx;
return d;
}
void solve(int a)
{
int b=n/a;LL x,y;int d=exgcd(a,b,x,y);
if(2%d==0)
{
x=((x*2/d)%abs(b/d)+abs(b/d))%abs(b/d);
y=(a*x-2)/b;
while(x*a-1<n){if(x*a-1>=0) q.insert(x*a-1);x+=abs(b/d);}
}
}
int main()
{
scanf("%d",&n);int len=sqrt(n);
if(n==1){printf("None");return 0;}
for(int i=1;i<=len;i++) if(n%i==0) solve(i),solve(n/i);
for(set<LL>::iterator i=q.begin();i!=q.end();i++) printf("%lld\n",*i);
}