hdu 3589 Jacobi symbol(欧拉准则暴力求解+分解质因数+素数筛表)

Jacobi symbol

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 514    Accepted Submission(s): 193


Problem Description
Consider a prime number p and an integer a !≡ 0 (mod p). Then a is called a quadratic residue mod p if there is an integer x such that x 2 ≡ a (mod p), and a quadratic non residue otherwise. Lagrange introduced the following notation, called the Legendre symbol, L (a,p):



For the calculation of these symbol there are the following rules, valid only for distinct odd prime numbers p, q and integers a, b not divisible by p:



The Jacobi symbol, J (a, n) ,is a generalization of the Legendre symbol ,L (a, p).It defines as :
1.  J (a, n) is only defined when n is an odd.
2.  J (0, n) = 0.
3.  If n is a prime number, J (a, n) = L(a, n).
4.  If n is not a prime number, J (a, n) = J (a, p1) *J (a, p2)…* J (a, pm), p1…pm is the prime factor of n.
 

Input
Two integer a and n, 2 < a< =10 6,2 < n < =10 6,n is an odd number.
 

Output
Output J (a,n)
 

Sample Input
  
  
3 5 3 9 3 13
 

Sample Output
  
  
-1 0 1
 

Author
alpc41
 

Source
题目分析:
欧拉准则可以用于判断这个数是否能够二次剩余,其中要筛取素数表,来求取质因数,暴力求解即可
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX 1000007

using namespace std;

typedef long long LL;

int a,n;

int prime[MAX];
int vis[MAX];
int cnt;

void init ( )
{
    for ( int i = 1 ; i < MAX ; i++ ) vis[i] = 1;
    cnt = 0;
    vis[1] = vis[0] = 0;
    for ( LL i = 2 ; i < MAX ; i++ )
    {
        if ( !vis[i] ) continue;
        vis[i] = cnt , prime[cnt++] = i;
        for ( LL j = i*i ; j < MAX ; j+= i )
            vis[j] = 0;
    }
}

int factor[MAX];
int sum;

void pre ( int n )
{
    sum = 0;
    for ( int i = 0 ; i < cnt && prime[i] <= n ; i++ )
    {
        while ( !(n%prime[i]) ) 
        {
            factor[sum++] = prime[i];
            n /= prime[i];
        }
    }
    if ( n != 1 ) factor[sum++] = n;
}

int pow ( LL a , LL n , LL p )
{
    if ( n == 0 ) return 1;
    LL temp = pow ( a , n/2 , p )%p;
    if ( n&1 ) return (int)(temp*temp%p*a%p);
    else return (int)(temp*temp%p);
}

int euler_check ( int a , int n )
{
    if ( a%n == 0 ) return 0;
    int temp = pow ( a , (n-1)/2 , n );
    if ( temp == 1 ) return 1;
    else return -1; 
}

int main ( )
{
    init ( );
    while ( ~scanf ( "%d%d" , &a , &n ) )
    {
        pre ( n );
        int ans = 1;
        for ( int i = 0 ; i < sum ; i++ )
            ans *= euler_check ( a , factor[i] );
        printf ( "%d\n" , ans );
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值