专栏文章

P11961 的一个无脑做法

休闲·娱乐参与者 3已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@minqz6fl
此快照首次捕获于
2025/12/02 06:55
3 个月前
此快照最后确认于
2025/12/02 06:55
3 个月前
查看原文
O(p0.25)O(p^{0.25}) 找到最小原根 gg
然后我们知道,对于所有 xφ(p)x \perp \varphi(p)xxgxg^x 必定是 pp 的一个原根。
所以我们只需要解出方程 gxa(modp)g^x \equiv a \pmod p,判断是否有 xφ(p)x \perp \varphi(p) 就做完了。这不是 BSGS 板子吗。
我贺了板子,实际上 φ(p)=p1\varphi(p)=p-1,都不用写函数求。代码应该是很短的。
以下是我的代码。
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T, n, d, P, qwq, x, y;
map<long, long> mp;
int exgcd(int a, int b, int &x, int &y){
	if (!b){
		x = 1, y = 0;
		return a;
	}
	int g = exgcd(b, a % b, x, y);
	swap(x, y);
	y -= a / b * x;
	return g;
}
int inv(int k, int p){
	exgcd(k, p, x, y);
	return (x % p + p) % p;
}
int qpow(int x, int k, int mod){
	int ans = 1;
	while (k){
		if (k & 1)
			ans = ans * x % mod;
		x = x * x % mod;
		k >>= 1;
	}
	return ans;
}
int bsgs(int a, int b, int p){
	mp.clear();
	int blo = ceil(sqrt(p)), tmp = b;
	for (int i = 0; i <= blo; i++){
		mp[tmp] = i;
		tmp = tmp * a % p;
	}
	int tx = qpow(a, blo, p);
	tmp = 1;
	for (int i = 1; i <= blo; i++){
		tmp = tmp * tx % p;
		if (mp[tmp])
			return i * blo - mp[tmp];
	}
	return -1;
}
int exbsgs(int a, int b, int p){
	//if (p == 1 || (b %= p) == 1)
	//	return 0;
	int g = __gcd(a, p), k = 0, prod = 1;
	while (g > 1){
		if (b % g > 0)
			return -1;
		k++;
		b /= g;
		p /= g;
		prod = prod * (a / g) % p;
		if (prod == b)
			return k;
		g = __gcd(a, p);
	}
	int res = bsgs(a, b * inv(prod, p) % p, p);
	return (res == -1 ? res : res + k);
}
vector<int> ans, di;
int gphi(int x){
	int tx = x, res = x;
	for (int i = 2; i * i <= tx; i++){
		if (tx % i == 0){
			res = res / i * (i - 1);
			while (tx % i == 0)
				tx /= i;
		}
	}
	if (tx > 1)
		res = res / tx * (tx - 1);
	return res;
}
bool pan(int x){
	if (x == 1 || x == 2 || x == 4)
		return 1;
	if (x % 2 == 0)
		x /= 2;
	vector<int> tmp;
	tmp.clear();
	if (x % 2 == 0)
		tmp.emplace_back(2);
	for (int i = 3; i * i <= x; i += 2){
		if (x % i == 0){
			if (tmp.size())
				return 0;
			tmp.emplace_back(i);
			while (x % i == 0)
				x /= i;
		}
	}
	if (x > 1 && tmp.size())
		return 0;
	return 1;
}
void work(int x){
	if (!(x & 1)){
		di.emplace_back(2);
		while (!(x & 1))
			x >>= 1;
	}
	for (int i = 3; i * i <= x; i += 2){
		if (x % i == 0){
			di.emplace_back(i);
			while (x % i == 0)
				x /= i;
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> T;
	while (T--){
		cin >> d >> n;
		if (!pan(n)){
			cout << "0\n\n";
			continue;
		}
		P = gphi(n);
		ans.clear();
		di.clear();
		work(P);
		for (int i = 1; i <= n; i++){
			if (__gcd(i, n) != 1)
				continue;
			bool chk = 1;
			for (auto x : di)
				if (qpow(i, P / x, n) == 1){
					chk = 0;
					break;
				}
			if (chk){
				qwq = i;
				break;
			}
		}
		int awa = exbsgs(qwq, d, n);
	//	cerr << awa << "\n";
		if (awa == -1 || __gcd(awa, P) != 1)
			cout << "No\n";
		else
			cout << "Yes\n";
	}
	return 0;
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...