URAL1132 Square Root 二次剩余模版题

关于二次剩余的介绍:http://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm

二次剩余的模版:

inline ll pow_mod(ll a,ll k,ll mo)
{
	ll ans=1;
	while(k)
	{
		if(k%2) ans=ans*a%mo;
		a=a*a%mo;
		k>>=1;
	}
	return ans%mo;
}
inline int modsqr(int a,int n)
{
	int b,k,i,x;
	if(n==2) return a%n;
	if(pow_mod(a,(n-1)/2,n)==1)
	{
		if(n%4==3)
			x=pow_mod(a,(n+1)/4,n);
		else
		{
			for(b=1;pow_mod(b,(n-1)/2,n)==1;b++);
			i=(n-1)/2;
			k=0;
			do{
				i/=2;
				k/=2;
				if((pow_mod(a,i,n)*(ll)pow_mod(b,k,n)+1)%n==0)
					k+=(n-1)/2;
			}while(i%2==0);
			x=(pow_mod(a,(i+1)/2,n)*(ll)pow_mod(b,k/2,n))%n;
		}
		if(x*2>n) x=n-x;
		return x;
	}
	return -1;
}

此题在n==2的时候特判一下答案就可以了。

#include<cstdio>
#define ll long long
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline ll pow_mod(ll a,ll k,ll mo)
{
	ll ans=1;
	while(k)
	{
		if(k%2) ans=ans*a%mo;
		a=a*a%mo;
		k>>=1;
	}
	return ans%mo;
}
inline int modsqr(int a,int n)
{
	int b,k,i,x;
	if(n==2) return a%n;
	if(pow_mod(a,(n-1)/2,n)==1)
	{
		if(n%4==3)
			x=pow_mod(a,(n+1)/4,n);
		else
		{
			for(b=1;pow_mod(b,(n-1)/2,n)==1;b++);
			i=(n-1)/2;
			k=0;
			do{
				i/=2;
				k/=2;
				if((pow_mod(a,i,n)*(ll)pow_mod(b,k,n)+1)%n==0)
					k+=(n-1)/2;
			}while(i%2==0);
			x=(pow_mod(a,(i+1)/2,n)*(ll)pow_mod(b,k/2,n))%n;
		}
		if(x*2>n) x=n-x;
		return x;
	}
	return -1;
}
int main()
{
	int a,n,t;
	t=read();
	while(t--)
	{
		a=read();n=read();
		int ans=modsqr(a,n);
		if(ans==-1) puts("No root");
		else if(n==2) puts("1");
		else printf("%d %d\n",ans,n-ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值