《P11961 [GESP202503 五级] 原根判断》
·
题目背景
对应的选择、判断题:试题 - GESP 202503 C++ 五级 - 洛谷有题
截止 2025 年 3 月,本题可能超出了 GESP 考纲范围。在该时间点下,原根是 NOI 大纲 8 级知识点(NOI 级),而相对简单的无需原根知识的做法中,使用的费马小定理与欧拉定理也属于 NOI 大纲 7 级知识点(提高级),且均未写明于 GESP 大纲中。需要注意,GESP 大纲和 NOI 大纲是不同的大纲。
若对题目中原根这一概念感兴趣,可以学习完成 【模板】原根。
题目描述
小 A 知道,对于质数 p 而言,p 的原根 g 是满足以下条件的正整数:
- 1<g<p;
- gp−1modp=1;
- 对于任意 1≤i<p−1 均有 gimodp=1。
其中 amodp 表示 a 除以 p 的余数。
小 A 现在有一个整数 a,请你帮他判断 a 是不是 p 的原根。
输入格式
第一行,一个正整数 T,表示测试数据组数。
每组测试数据包含一行,两个正整数 a,p。
输出格式
对于每组测试数据,输出一行,如果 a 是 p 的原根则输出 Yes,否则输出 No。
输入输出样例
输入 #1复制
3 3 998244353 5 998244353 7 998244353
输出 #1复制
Yes Yes No
说明/提示
数据范围
对于 40% 的测试点,保证 3≤p≤103。
对于所有测试点,保证 1≤T≤20,3≤p≤109,1<a<p,p 为质数。
代码实现:
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
ll qpow(ll a, ll b, ll mod)
{
ll res = 1;
a %= mod;
while (b)
{
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
vector<ll> get_factor(ll x)
{
vector<ll> fac;
for (ll i = 2; i * i <= x; i++)
{
if (x % i == 0)
{
fac.push_back(i);
while (x % i == 0) x /= i;
}
}
if (x > 1) fac.push_back(x);
return fac;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--)
{
ll a, p;
cin >> a >> p;
ll phi = p - 1;
vector<ll> fac = get_factor(phi);
bool ok = true;
for (ll q : fac)
{
ll exp = phi / q;
if (qpow(a, exp, p) == 1)
{
ok = false;
break;
}
}
if (ok) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}
更多推荐

所有评论(0)