P6091-[模板]原根

1|0正题

题目链接:https://www.luogu.com.cn/problem/P6091


1|1题目大意

给出一个数p,求出它的所有在[0,p]的原根。


1|2解题思路

原根的定义,δp(a)表示一个最小的n使得an1(mod p),若gcd(a,p)=1δp(a)=φ(p)ap的一个原根。

两个个结论就是一个数有原根当且仅当它为2,4,pa,2pa(其中p为奇质数,aN+)。还有若g表示最小正原根,那么其他原根可以被表示为gk%p( gcd(φ(p),k)=1 )

这两个结论在洛谷题解都有详细证明,这里就不多赘述了。

那么考虑如何求出最小正原根,因为原根的数量大约有φ(φ(p))个,所以密集度比较高,据说最小正原根约是O(n2.5)级别的。

所以考虑直接枚举,但是我们判定的时候肯定不能从1φ(p)枚举来判断。

我们还需要用到一个结论就是如果对于gcd(a,p)=1ak1(mod p)(也就是kan的阶),那么有k|φ(p)。所以我们需要判定φ(p)的所有因子?看起来还是很大,但是我们显然有ak1(mod p)那么akx1(mod p)其中xN+。所以我们只需要枚举φ(p)k(其中kφ(p)的质因子)即可,因为这些数包含了其他数的倍数。

时间复杂度O(n2.5logn+nlogn)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long using namespace std; const ll N=1e6+10; ll T,n,d,cnt,phi[N],pri[N]; bool v[N],rt[N]; vector<int> q; void prime(){ phi[1]=1; for(ll i=2;i<N;i++){ if(!v[i])pri[++cnt]=i,phi[i]=i-1; for(ll j=1;j<=cnt&&i*pri[j]<N;j++){ v[i*pri[j]]=1; if(i%pri[j]==0){ phi[i*pri[j]]=phi[i]*pri[j]; break; } phi[i*pri[j]]=phi[i]*phi[pri[j]]; } } rt[2]=rt[4]=1; for(ll i=2;i<=cnt;i++){ for(ll j=1;j<N;j*=pri[i])rt[j]=1; for(ll j=2;j<N;j*=pri[i])rt[j]=1; } return; } ll power(ll x,ll b,ll p){ ll ans=1; while(b){ if(b&1)ans=ans*x%p; x=x*x%p;b>>=1; } return ans; } ll gcd(ll x,ll y) {return (!y)?x:gcd(y,x%y);} void dec_phi(ll x){ for(ll i=1;i<=cnt&&pri[i]*pri[i]<=x;i++) if(x%pri[i]==0){ q.push_back(pri[i]); while(x%pri[i]==0)x/=pri[i]; } if(x!=1)q.push_back(x); return; } bool check(ll x){ if(power(x,phi[n],n)!=1)return 0; for(ll i=0;i<q.size();i++) if(power(x,phi[n]/q[i],n)==1) return 0; return 1; } signed main() { scanf("%lld",&T); prime(); while(T--){ scanf("%lld%lld",&n,&d);q.clear(); if(!rt[n]){printf("0\n\n");continue;} dec_phi(phi[n]);ll g=1; while(!check(g))g++; ll tmp=1;q.clear(); for(ll i=1;i<=phi[n];i++){ tmp=tmp*g%n; if(gcd(phi[n],i)==1) q.push_back(tmp); } printf("%lld\n",q.size()); sort(q.begin(),q.end()); for(ll i=1;i<=q.size()/d;i++) printf("%lld ",q[i*d-1]); putchar('\n'); } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14248648.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(121)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示