题目背景

对应的选择、判断题:试题 - 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;
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐