二次互反律


前面我們已經學習過了高斯引理,那么二次互反律就呼之欲出了

我們先介紹一下什么是二次互反律

假設p,q是兩個奇素數,二次互反律就是要研究p對q的勒讓德符號和q對p的勒讓德符號之間的關系

二次互反律給出了結論:

legendre(p,q)*legendre(q,p)=(-1)^((p-1)*(q-1)/4)

我們通過證明下式來證明二次互反律,它蘊含着二次互反律

T(p,q)+T(q,p)=(p-1)*(q-1)/4

怎么證明T函數具有這樣一個奇妙性質呢?

不想寫太多證明的東西,看幾張圖片直觀感受一下你就明白了,其實這個公式不太難

這是最常見的利用填矩形的方式證明,直線上方點數就是T(p,q),下方點數就是T(q,p)

圖一:T(5,3)+T(3,5)=2*3

 

圖二 T(11,7)+T(7,11)=3*5

 

 圖片是用java繪制的,代碼分享給大家:

 

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;

public class test{
	static int width=800,height=800,r=4,d=80;
	public static void paint_point(int x,int y,Graphics g) {
		x=d+d*x;
		y=height-d-d*y;
		g.setColor(Color.black);
		g.fillOval(x-r, y-r, r<<1, r<<1);
	}
	public static void paint_line(int fx,int fy,int sx,int sy,Graphics g) {
		fx=d+d*fx;
		fy=height-d-d*fy;
		sx=d+d*sx;
		sy=height-d-d*sy;
		g.setColor(Color.BLACK);
		g.drawLine(sx, sy, fx, fy);
	}
	public static void label_x(int p,int q,int i,Graphics g) {
		String str="["+p+"*"+i+"/"+q+"]";
		int x=d*i+60,y=height-d;
		g.drawString(str, x, y);
	}
	public static void label_y(int p,int q,int i,Graphics g) {
		String str="["+p+"*"+i+"/"+q+"]";
		int x=d,y=height-i*d-d;
		g.drawString(str, x, y);
	}
	public static void main(String[] args) {
		JFrame jf=new JFrame() {
			public void paint(Graphics g) {
				g.setColor(Color.white);
				g.fillRect(0, 0, width, height);
				int p=13,q=11;//在這里修改你想要的值
				for(int i=1;i<=p/2;i++) {
					for(int j=1;j<=q/2;j++) {
						paint_point(i,j,g);
					}
				}
				for(int x=1;x<=p/2;x++) {
					label_x(q, p, x, g);
				}
				for(int y=1;y<=q/2;y++) {
					label_y(p, q, y, g);
				}
				paint_line(0, 0, p, q,g);
			}
		};
		jf.setSize(width, height);
		jf.setVisible(true);
		jf.setDefaultCloseOperation(3);
	}
}

  

 話題收回來,我們知道了T(p,q)+T(q,p)=(p-1)*(q-1)/4

將兩邊作為-1的指數,就得到了二次互反律。

 有了二次互反律,我們就可以高效解決判斷二次剩余的問題了

下面我們給出算法:

求a對p的勒讓德符號:

  利用勒讓德符號的周期性,先將a取模p

  將a分解素因數,保留次數為奇數的素因素{a1,a2....an}

  對2,利用高斯引理的推論直接計算,對其他奇素數,利用二次互反律計算

  利用勒讓德符號的可乘性,返回結果的積

此算法的瓶頸還是在於分解素因數,下面給出C++代碼實現

 

#include<iostream>
using namespace std;
//用於分解素因子 
struct breaker{
	int num,cur=2;
	breaker(int num){
		this->num=num;
	}
	void next(int&res,int&pow){
		pow=0;res=0;
		while(num%cur==0){
			res=cur;
			pow++;num/=cur;
		}
		cur++;
	}
	//獲取下一個奇數次素因子 
	int get(){
		int res,pow;
		next(res,pow);
		while(pow%2==0&&num>1){
			next(res,pow);
		}
		return res;
	}
};
//計算a對p的勒讓德符號,要求p是素數,a不是p的倍數 
int legendre(int a,int p){
	a%=p;
	breaker bk(a);
	int temp=bk.get();
	int res=1;
	if(temp==2){
		//使用高斯引理推論計算 
		res*=((p*p-1)&8)?-1:1;
		temp=bk.get();
	}
	while(temp){
		//使用二次互反律計算 
		res*=legendre(p,temp)*(((p-1)&(temp-1)&2)?-1:1);
		temp=bk.get();
	}
	return res;
}
int main(){
	cout<<legendre(137,227);
}

 

希望對大家有幫助!

  

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM