ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

二次剩余小记

2020-08-22 09:02:33  阅读:200  来源: 互联网

标签:剩余 node return 二次 int pmod real 小记 equiv


看 \(\text{yyb}\) 的博客看到的,发现似乎并没有想象中的那么难,就学了一下,过了板题,这里记录一下,暂时还是只会二次剩余, \(n\) 次剩余暂时先放一下。

模数为奇素数

下文的 \(p\) 即是模数。

我们称 \(n\) 为模 \(p\) 意义下的二次剩余当且仅当存在 \(x\) 使得 \(x^2\equiv n\pmod p,x\in \mathbb{N}\) 。下文的 \(\mathbb{N}\) 其实是自然数集。

  • 引理1

\((A+B)^p\equiv A^p+B^p\pmod{p}\)

  • 证明

显然只需要说明 \(\dbinom{p}{i}\equiv0\pmod p,s.t.\ \ 1\le i\le p-1\),然后我们发现如果 \(p\) 是个奇素数的话,那么分子里面的 \(p\) 就没有办法消去,于是就得证了。

  • 引理2

\(n^{\frac{n-1}{2}}\equiv 1\pmod p\)

是 \(n\) 是模 \(p\) 意义下的二次剩余的充要条件。

  • 证明

必要性 :设 \(x^2\equiv n\pmod p\),那么有 \(x^{p-1}\equiv 1\pmod p\) ,证毕。

充分性 :费马大定理的逆定理说了: \(x^{p-1}\equiv 1\pmod p\iff x\in \mathbb{N}\) (不考虑 \(0\)),所以证毕。


接下来,我们考虑随机出一个 \(a\) 使得 \(a^2-n\) 不是一个二次剩余,这样的期望尝试次数大概为 \(2\),再设 \(i^2=a^2-n\) ,这里的 \(i\) 显然就不属于 \(\mathbb{N}\) ,我们把它视作虚数之类的东西就好了。然后我们发现就有个性质:

  • 性质

\[i^{p-1}\equiv -1\pmod p \]

证明 :首先我们知道 \((i^2)^{\frac{p-1}{2}}\equiv (a^2-n)^{\frac{p-1}{2}}\not\equiv -1\pmod p\) (因为 \(a^2-n\) 不是一个二次剩余),然后又有 \((i^2)^{p-1}\equiv 1\pmod p\),所以 \(i^{p-1}\equiv 1\pmod p\)。


我们可(bu)以(neng)发现:

\[(a+i)^{p+1}\equiv (a+i)^p(a+i)\equiv(a^p+i^p)(a+i)\equiv (a-i)(a+i) \]

\[\equiv a^2-i^2\equiv n\pmod p \]

就是说 \((a+i)^{p+1}\equiv n\pmod p\),所以说 \(\sqrt n\equiv (a+i)^{\frac{p+1}{2}}\pmod p\)。

可能有人有疑问,\((a+i)^{\frac{p+1}{2}}\) 有没有可能不是一个整数,显然如果你保证有解的话它显然就是一个整数。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define int long long

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int p,sqri;

int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = 1ll * a * a % p) if (b & 1) res = 1ll * res * a % p;
	return res;
}
int mul (int a,int b){return 1ll * a * b % p;}
int dec (int a,int b){return a >= b ? a - b : a + p - b;}
int add (int a,int b){return a + b >= p ? a + b - p : a + b;}

struct node{
	int real,imag;
	node (int _real,int _imag) : real (_real) , imag (_imag) {}
	node operator * (node b){return node (add (1ll * real * b.real % p,1ll * imag * b.imag % p * sqri % p),add (1ll * real * b.imag % p,1ll * b.real * imag % p));}
	node operator + (node b){return node (add (real,b.real),add (imag,b.imag));}
	node operator ^ (int b){node a = *this,res = node (1,0);for (;b;b >>= 1,a = a * a) if (b & 1) res = res * a;return res;}
};

bool check_if_qs (int n){//判断是否是一个二次剩余 
	return qkpow (n,(p - 1) >> 1) == 1;
}

bool tryit (int n){
	if (n == 0){
		puts ("0");
		return 1;
	}
	int a = rand ();sqri = dec (mul (a,a),n);
	if (!a || !check_if_qs (sqri)){
		int x0 = (node (a,1) ^ (p + 1 >> 1)).real;
		int x1 = p - x0;if (x0 > x1) swap (x0,x1);
		write (x0),putchar (' '),write (x1),putchar ('\n');
		return 1;
	}
	else return 0;
} 

signed main(){
	int T;read (T);
	while (T --> 0){
		int n;read (n,p);
		if (!check_if_qs (n) && n) puts ("Hola!");
		else while (1) if (tryit (n)) break;
	}
	return 0;
}

标签:剩余,node,return,二次,int,pmod,real,小记,equiv
来源: https://www.cnblogs.com/Dark-Romance/p/13544309.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有