【JZOJ 3909】Idiot 的乘幂

题面:


正文:

把题目中的方程组组合在一起就变成了:

\(X^{a+c}\equiv b \cdot d (\mod p)\)

那这时,我们假定两个数\(x\)\(y\),使得:

\(ax + cy = 1\)

于是:

\(X^{ax+cy}\equiv X \equiv b^x \cdot d^y (\mod p)\)

那我们就可以根据\(ax+cy=1\)跑一遍扩欧,再根据\(X \equiv b^x \cdot d^y (\mod p)\),就能得出\(X\)了。


但是,你以为出题人这么善良吗?

\(x\)\(y\)可能是负数,做\(b^x \cdot d^y\) 时就相当于 \(\frac{1}{b^{(-x)}} \cdot \frac{1}{d^{(-y)}}\), 因为有膜法技能同余,这里肯定出锅。

所以我们还要给\(b\)\(d\)求个逆元,同样,也是用扩欧。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ZYC using
#define AK namespace
#define IOI std
#define ll long long

ZYC AK IOI;

const int N = 0;

ll exgcd(ll a, ll b, ll &x, ll &y)
{
	if(b == 0)
	{
		x = 1, y = 0;
		return a;
	}
	ll val = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return val;
}
ll qpow(ll a, ll b, ll p)
{
	ll ans = 1;
	for (; b; b >>= 1)
	{
		if(b & 1) ans = (ans * a+p) % p;
		a = (a * a+p) % p;
	}
	return ans;
}

ll t, a, b, c, d, bf, df, p, x, y, X, public_;

int main()
{
	for(scanf("%lld", &t); t--;)
	{
		scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &p);
		exgcd(a, c, x, y);
		bf = b, df = d;
		if (x < 0)
			exgcd(b, p, bf, public_), x = -x;
		if (y < 0)
			exgcd(d, p, df, public_), y = -y;
		X = qpow((bf % p + p)%p, x, p) * qpow((df % p + p)%p, y, p)%p ;  
		if((qpow(X, a, p) == b % p) && (qpow(X, c, p) == d % p))
			printf("%lld\n", X);
		else puts("No Solution!");
	}
	return 0;
}
posted @ 2019-12-13 18:38  Jayun  阅读(204)  评论(0)    收藏  举报