1. 程式人生 > >hdu 3589 Jacobi symbol (二次剩餘勒讓德符號)

hdu 3589 Jacobi symbol (二次剩餘勒讓德符號)

題目連結

題意:交代一下勒讓德符號與二次剩餘,然後告訴你J(a,n)與L的關係,給定a,n,求J(a,n)。

二次剩餘的原理我並沒有搞太懂= =,想著畢竟不常見,會用板子就好了。在知道如何求勒讓德符號的情況下,只需要將n分解質因數,假設n=p1^k1 * p2^k2 * ... *pm^km,則答案為J(a,p1)^k1 * J(a,p2)^k2 * ... * J(a,pm)^km = L(a,p1)^k1 * L(a,p2)^k2 * ... * L(a,pm)^km。

程式碼如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define For(i,a,b) for(int i=a;i<=b;i++)
#define p_b push_back
#define N 1005
int quick_mod(int a,int b,int c) { int ans = 1; while (b) { if (b&1)ans=(ans*1ll*a)%c; b/= 2; a=(a*1ll*a)%c;} return ans; }
bool notprime[N];
int prime[200],cnt;
void init(){
	notprime[1]=1;
	For(i,2,N-1){
		if(!notprime[i]){
			prime[cnt++]=i;
		}
		for(int j=0;j<cnt&&i*prime[j]<N;j++){
			notprime[i*prime[j]]=1;
			if(i%prime[j]==0){
				break;
			}
		}
	}
}
vector<int> fac;
int Legender(int a,int p)//求勒讓德符號
{
	int ans=(quick_mod(a, (p - 1) / 2, p)%p+p)%p;
	if(ans==p-1) return -1;
	else return ans;
}
int solve(int n,int p){
	fac.clear();
	int x=p;
	for(int i=0;i<cnt&&prime[i]<=x;i++){
		while(x%prime[i]==0) x/=prime[i],fac.p_b(prime[i]);
	}
	if(x>1)fac.p_b(x);
	int tmp=1;
	for(int i=0;i<(int)fac.size();i++){
		tmp*=Legender(n,fac[i]);
	}
	return tmp;
}
int main()
{
	init();
	int n,p;
	while (scanf("%d%d",&n,&p)!=EOF)
	{
		printf("%d\n",solve(n,p));
	}
}