【Atcoder】 [ARC158D] Equation

文章介绍了如何利用模运算性质解决等式F(x,y,z)≡t*G(x,y,z)(modp)的问题。当等式左边的次数高于右边时,可以通过随机选取x,y,z的值找到一组解。在无解的情况概率较低的情况下,不断随机尝试直到找到合法解的方法被提出。代码示例展示了具体的实现过程。
摘要由CSDN通过智能技术生成

题目链接

Atcoder方向
Luogu方向

题目解法

考虑等式两边都为多次齐次项
令等式左边的值为 F ( x , y , z ) F(x,y,z) F(x,y,z),等式右边的值为 G ( x , y , z ) G(x,y,z) G(x,y,z)
F ( x , y , z ) ≡ t ∗ G ( x , y , z )    ( m o d    p ) F(x,y,z)\equiv t*G(x,y,z)\;(mod \;p) F(x,y,z)tG(x,y,z)(modp)
因为等式左边比等式右边高一次
所以 F ( x t , y t , z t ) ≡ G ( x t , y t , z t )    ( m o d    p ) F(\frac{x}{t},\frac{y}{t},\frac{z}{t})\equiv G(\frac{x}{t},\frac{y}{t},\frac{z}{t})\;(mod\;p) F(tx,ty,tz)G(tx,ty,tz)(modp)

由式子可以 t = F ( x , y , z ) ∗ G ( x , y , z ) − 1 t=F(x,y,z)*G(x,y,z)^{-1} t=F(x,y,z)G(x,y,z)1
因为 t ≠ 0 t\ne 0 t=0,所以 F ( x , y , z ) F(x,y,z) F(x,y,z) G ( x , y , z ) G(x,y,z) G(x,y,z) 不等于 0 0 0,就一定有一组解

考虑没有解的情况出现概率较小( < 1 4 <\frac{1}{4} <41),所以考虑随机 x , y , z x,y,z x,y,z 的值,直到找到一组合法的解

#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
int qmi(int a,int b,int p){
	int res=1;
	for(;b;b>>=1){
		if(b&1) res=res*a%p;
		a=a*a%p;
	}
	return res;
}
void work(){
	int n=read(),p=read();
	while(true){
		int x=rand()%(p-1)+1,y=rand()%(p-1)+1,z=rand()%(p-1)+1;
		if(x==y||x==z||y==z) continue;
		int xn=qmi(x,n,p),yn=qmi(y,n,p),zn=qmi(z,n,p);
		int mi0=(x+y+z)%p,mi1=(xn+yn+zn)%p,mi2=(xn*xn%p+yn*yn%p+zn*zn%p)%p;
		int Left=mi0*mi1%p*mi2%p,Right=(xn*xn%p*xn%p+yn*yn%p*yn%p+zn*zn%p*zn%p)%p;
//		cout<<x<<' '<<y<<' '<<z<<' '<<mi0<<' '<<mi1<<' '<<mi2<<' '<<Left<<' '<<Right<<'\n';
		if(!Right||!Left) continue;
		int t=Right*qmi(Left,p-2,p)%p;
		x=x*t%p,y=y*t%p,z=z*t%p;
//		cout<<t<<'\n';
		if(x>y) swap(x,y);
		if(x>z) swap(x,z);
		if(y>z) swap(y,z);
		printf("%lld %lld %lld\n",x,y,z);
		return;
	}
} 
signed main(){
	srand(time(NULL));
	int T=read();
	while(T--) work();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值