/**Time: 156 ms, 但是当我把求素因子拆出来的时候,居然600ms
*题目大意:
*        求二次剩余,求雅克比符号,然后根据性质把雅克比符号转换为勒让德符号。
*        注意判断勒让德符号的结果,可以用欧拉准则,L(a, n),当 n|a时,结果为0,
*        否则用a^((n - 1) / 2) mod n来求。(欧拉函数的适用范围是当n为奇素数)
*解题思路:
*        直接用欧拉准则来模拟即可。不需要管题目的一大堆性质,注意提取题目有用的信息。
*题目困惑:
*        当用J(a, n)中的n不是素数要装换为 J (a, n) = J (a, p1) *J (a, p2)…* J (a, pm),
*        p1…pm is the prime factor of n.的时候,2是偶数,但是此题还是可以用
*        欧拉准则来处理。
*(傻逼了我,题目中根本就不可能出现2,因为n是奇数,那么n的素因子是不可能出现2的。)
*/
View Code
  1 #include <iostream>
  2 #include <cmath>
  3 using namespace std;
  4 
  5 const int MAX = 1000000 + 1;
  6 int prime[MAX];
  7 bool isPrime[2 * MAX];
  8 /**
  9     prim:    将素数压入此数组中,如2,3,5,7,11,13,17,19... 
 10     isPrime:    下表为i的数,是否为素数 
 11     n:        判断小于等于n的数,prime的上限
 12     m:        isPrime的上限(n <= m <= n*n)
 13     
 14     返回:素数的个数 
 15 */
 16 int getPrime(int*prime, bool*isPrime, int n, int m)
 17 {
 18     int p,i,j;
 19     memset(isPrime, 1, m);        
 20     p=isPrime[0]=isPrime[1]=0;
 21     for(i=2;i<=n;i++)
 22         if(isPrime[i])
 23             for(prime[p++]=i,j=2*i;j<=m;j+=i)
 24                 isPrime[j] = false;
 25     return p;
 26 }
 27 
 28 //整数分解(>=2)(分解为质因子相乘)
 29 //Prime做到√maxn就行了,isPrime做到maxn
 30 int resolve(int x, int *arr) 
 31 {
 32     int len = 0;
 33     for(int i = 0; x != 1; i ++) 
 34     {
 35         if(isPrime[x])
 36         {
 37             arr[len ++] = x;
 38             break;
 39         }
 40         while(x % prime[i] == 0)
 41         {
 42             arr[len ++] = prime[i];
 43             x /= prime[i];
 44         }
 45     }
 46     return len;
 47 }
 48 
 49 /**
 50     返回(a^b)%w;
 51     O(lg(b))的效率
 52 */
 53 //注意中间结果是否会溢出
 54 int mod_pow(__int64 a, __int64 k, __int64 m) 
 55 {
 56     static __int64 r;
 57     for(r=1; k; k>>=1, a=a*a%m)
 58         if(k&1)    r = r*a%m;
 59     return (int)r;
 60 }
 61 
 62 int oula_judge(int a, int n)
 63 {
 64     if(a % n == 0)
 65         return 0;
 66     int t = (n - 1) / 2;
 67     int temp = mod_pow(a, t, n);
 68     if(temp == 1)
 69         return 1;
 70     else
 71         return -1;
 72 }
 73 
 74 int main(void)
 75 {
 76     getPrime(prime, isPrime, 1000000, 2 * 1000000);
 77     int a, n;
 78     while(scanf("%d %d", &a, &n) == 2)
 79     {
 80         if(isPrime[n] == 1)
 81         {
 82             cout << oula_judge(a, n) << endl;
 83         }
 84         else
 85         {
 86             //cout << "conm,e" << endl;
 87             int ans = 1;
 88             //注释的这一段600ms
 89             /*for(int i = 0; n != 1; i++)
 90             {
 91                 int cnt = 0;
 92                 while(n % prime[i] == 0)
 93                 {
 94                     n /= prime[i];
 95                     cnt++;
 96                 }
 97                 int t = oula_judge(a, prime[i]);
 98                 ans *= (int)pow((double)t, (double)cnt);
 99             }*/
100             int factor[100000];
101             int len = resolve(n, factor);
102             for(int i = 0; i < len; i++)
103             {
104                 ans *= oula_judge(a, factor[i]);
105             }
106             cout << ans << endl;
107         }
108     }
109     return 0;
110 }
posted on 2012-07-18 22:22  cchun  阅读(350)  评论(0编辑  收藏  举报