题目链接:Click here~~
题意:
给你一个数 n,保证 n 是两个素数 p、q 相乘的乘积,问存在几个 x ,使得 x*x = x (mod n)。(x < n)
解题思路:
首先要弄懂符号 (mod n) 的意思,若 a = b(mod n),意思是 a 和 b 分别除以 c 以后余数相同。
这种式子一般可以写成 a + k*n = b的形式。
于是本题等价于求方程 x*x + k*n = x 的解。
可以将方程化简成这样的形式: k = x*(x-1) / (p*q).(k 为任意整数)。
1、当 k 为 0 时,x = 0 或 x = 1。且这两组解一定存在。
2、当 k 不为 0 时,x 和 x-1 中必定存在 p 和 q 这两个素因子,且各至多存在一个。
反证法:若 x 中存在 p 和 q 这两个素因子,则 x >= p*q ,即 x >= n,与 x < n 矛盾。
所以解只有两种情况:(1) x 中存在因子 p,x-1 中存在因子 q;(2) x 中存在因子 q,x-1 中存在因子 p。
对于情况(1),相当于给了两个式子 x%p=0 和 (x-1)%q=0。
也就是 x - pi = 0 和 x - qj = 1。于是得到了 pi - qj = 1。(gcd(p,q) = 1)
然后运用扩展欧几里得算法可以求得 i,j 的某组解,再将它适当调整到正值即可。
同理可解出情况(2)。
#include <stdio.h> #include <algorithm> using namespace std; #define N 35000 bool Not_Prime[N]; int P[4222]; void Prime() { int top = -1; for(int i=2;i<N;i++) if(!Not_Prime[i]) { P[++top] = i; for(int j=i+i;j<N;j+=i) Not_Prime[j] = true; } } void ExGcd(int a,int b,int &x,int &y) { if(b == 0) { x = 1; y = 0; return ; } ExGcd(b,a%b,x,y); int t = x; x = y; y = t - a/b*y; } int main() { int z,p,q,x,y,n,X1,X2; scanf("%d",&z); Prime(); while(z--) { scanf("%d",&n); for(int i=0;;i++) { if(n%P[i] == 0) { p = P[i]; q = n/P[i]; break; } } ExGcd(p,q,x,y); X1 = x<0 ? p*x+p*q : p*x; ExGcd(q,p,x,y); X2 = x<0 ? q*x+p*q : q*x; printf("%d %d %d %d\n",0,1,min(X1,X2),max(X1,X2)); } return 0; }