二次剩余学习笔记

注意,下面的运算都是在模意义下进行的。

给定 n,求 x2n

x 存在条件为 np12=1,证明用费马小定理,略。

如何求出 x,随机一个 不存在 二次剩余的值 a2n,设为 w2

这里可以把 w 理解为一个虚数。由于 w2 不存在二次剩余,所以

wp=wp1×w=(w2)p12×w=(a2n)p12×w=(1)×w=w

那么 (a+w)p+1=(ap+wp)(a+w)=(aw)(a+w)=a2w2=n

我们要求 (a+w)p+12,可以扩域计算。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')
		ch=getchar();
	while(ch>='0'&&ch<='9')
		s=s*10+ch-48,ch=getchar();
	return s;
}
int pown(int x,int y,int p)
{
	if(!y)
		return 1;
	int t=pown(x,y>>1,p);
	if(y&1)
		return 1LL*t*t%p*x%p;
	return 1LL*t*t%p;
}
mt19937 gen(time(0));
int t,n,p,a,k;
struct node{
	LL x,y;
	node operator*(const node&n)const{
		return (node){(x*n.x+y*n.y%p*k)%p,(y*n.x+x*n.y)%p};
	}
};
node pown(node x,int y)
{
	if(!y)
		return (node){1,0};
	node t=pown(x,y>>1);
	if(y&1)
		return t*t*x;
	return t*t;
}
int main()
{
	t=read();
	while(t--)
	{
		n=read(),p=read();
		if(!n)
		{
			puts("0");
			continue;
		}
		if(pown(n,p-1>>1,p)^1)
			puts("Hola!");
		else
		{
			while(1)
			{
				a=gen()%p,k=(1LL*a*a%p+p-n)%p;
				if(pown(k,p-1>>1,p)==1)
					continue;
				int g=pown((node){a,1},p+1>>1).x;
				if(p-g<g)
					printf("%d %d\n",p-g,g);
				else
					printf("%d %d\n",g,p-g);
				break;
			}
		}
	}
}
posted @   灰鲭鲨  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示