借鉴别人的,虚心学习
#include < iostream > #include < ctime > #include < cstdlib > #include < cmath > #include < algorithm > using namespace std; const int TIME = 12 ; // Miller测试次数 __int64 mod_mult(__int64 a, __int64 b, __int64 n) // 计算(a*b)%n { __int64 s = 0 ; a = a % n; while (b) { if (b & 1 ) { s += a; s %= n; } a = a << 1 ; a %= n; b = b >> 1 ; } return s;}__int64 mod_exp(__int64 a, __int64 b, __int64 n) // 计算(a^b)%n { __int64 d = 1 ; a = a % n; while (b >= 1 ) { if (b & 1 ) d = mod_mult(d,a,n); a = mod_mult(a, a, n); b = b >> 1 ; } return d;} bool Wintess(__int64 a, __int64 n) // 以a为基对n进行Miller测试并实现二次探测 { __int64 m,x,y; int i,j = 0 ; m = n - 1 ; while (m % 2 == 0 ) // 计算(n-1)=m*(2^j)中的j和m,j=0时m=n-1,不断的除以2直至n为奇数 { m = m >> 1 ; j ++ ; } x = mod_exp(a,m,n); for (i = 1 ;i <= j;i ++ ) { y = mod_exp(x, 2 ,n); if ((y == 1 ) && (x != 1 ) && (x != n - 1 )) // 二次探测 return true ; // 返回true时,n是合数 x = y; } if (y != 1 ) return true ; return false ;} bool miller_rabin(__int64 n, int times) // 对n进行s次的Miller测试 { __int64 a; int i; if (n == 1 ) return false ; if (n == 2 ) return true ; if (n % 2 == 0 ) return false ; srand(time(NULL)); for (i = 1 ;i <= times;i ++ ) { a = rand() % (n - 1 ) + 1 ; if (Wintess(a, n)) return false ; } return true ;} int main(){ __int64 a,p,tmp; bool prime; while (scanf( " %I64d%I64d " , & p, & a) != EOF) { if (a == 0 && p == 0 ) break ; prime = miller_rabin(p,TIME); if ( ! prime) // p不是素数,则判断(a^p)%p=a是否成立 { tmp = mod_exp(a,p,p); if (tmp == a) printf( " yes\n " ); else printf( " no\n " ); } else printf( " no\n " ); } system( " pause " ); return 0 ;}