本文同步发布至 洛谷
题解:P11961 [GESP202503 五级] 原根判断
题外话
CCF 是不是放错题了?虽然这道题也比较简单,但是不符合五级的水准啊!!!
题目分析
根据题目的要求,有三个条件,其中第一个条件是最好判的,因为数据就已经保证了,当然如果你也想判一下也无所谓。
接下来就看第二个条件,非常显然是一个模板的快速幂,可以在 O ( log n ) O(\log n) O(logn) 的时间复杂度内解决,也是比较容易的。
最难的就是第三个条件了,如果说你只想拿 40 分的话,也可以直接顺着打暴力,硬判,但是嘛,我们都是有追求的人,不能只关注者一点点的分,所以说我们要找规律。
我的数学老师杨老师,曾经说过一句话,正着来弄难,那就反着来弄,话句话说,这道题我们是不是可以直接反着判,看看哪些情况可能得到 1,哪些情况可能得不到 1。
接下来就是尝试。
如果说我们设 a k m o d p = 1 a^k \bmod p =1 akmodp=1,那么因为取余的两侧可以进行加,减,乘的运算,所以说我们又可以很轻松的得到这些式子 a k + 1 m o d p = a 1 m o d p a^{k+1}\bmod p=a^1 \bmod p ak+1modp=a1modp, a k + 2 m o d p = a 2 m o d p a^{k+2} \bmod p=a^2 \bmod p ak+2modp=a2modp, a k + n m o d p = a n m o d p a^{k+n} \bmod p=a^n\bmod p ak+nmodp=anmodp。
那么基于这些式子,我们是不是可以发现这个是一个长度为 k k k 的一个循环周期?
同时我们根据条件 2,是不是发现这个长度周期只有可能是 p − 1 p-1 p−1 的因数,那么我们直接枚举因数不就可以了?
这样的时间复杂度就是 O ( T × p − 1 × log p − 1 ) O(T\times \sqrt{p-1}\times \log_{p-1}) O(T×p−1×logp−1)。
代码实现
#include<bits/stdc++.h>
using namespace std;
long long quickpow(int a,int p,int mod){
if (p==0)return 1;
long long t=quickpow(a,p/2,mod);
t=t*t%mod;
if (p%2==1)t=t*a%mod;
return t%mod;
}
int main(){
int T;
cin>>T;
while (T--){
int a,p;
cin>>a>>p;
if (quickpow(a,p-1,p)!=1){
cout<<"No\n";
continue;
}
bool flag=true;
for (int i=2;i*i<=(p-1);i++){
if ((p-1)%i==0){
if (quickpow(a,i,p)==1||quickpow(a,(p-1)/i,p)==1){
flag=false;
break;
}
}
}
if (flag)cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}


1153

被折叠的 条评论
为什么被折叠?



