正题

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


题目大意

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


解题思路

原根的定义,\(\delta_p(a)\)表示一个最小的\(n\)使得\(a^n\equiv1(mod\ p)\),若\(gcd(a,p)=1\)且\(\delta_p(a)=\varphi(p)\)则\(a\)为\(p\)的一个原根。

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

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

那么考虑如何求出最小正原根,因为原根的数量大约有\(\varphi(\varphi (p))\)个,所以密集度比较高,据说最小正原根约是\(O(n^{2.5})\)级别的。

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

我们还需要用到一个结论就是如果对于\(gcd(a,p)=1\)且\(a^k\equiv 1(mod\ p)\)(也就是\(k\)是\(a\)模\(n\)的阶),那么有\(k|\varphi(p)\)。所以我们需要判定\(\varphi(p)\)的所有因子?看起来还是很大,但是我们显然有\(a^k\equiv 1(mod\ p)\)那么\(a^{kx}\equiv1(mod\ p)\)其中\(x\in N^+\)。所以我们只需要枚举\(\frac{\varphi(p)}{k}\)(其中\(k\)是\(\varphi(p)\)的质因子)即可,因为这些数包含了其他数的倍数。

时间复杂度\(O(n^{2.5}\log n+n\log n)\)


code

#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;
}

P6091-[模板]原根的更多相关文章

  1. x^a=b(mod c)求解x在[0,c-1]上解的个数模板+原根求法

    /************************************* 求解x^a=b(mod c) x在[0,c-1]上解的个数模板 输入:1e9>=a,b>=1,1e9>= ...

  2. FFT模板 生成函数 原根 多项式求逆 多项式开根

    FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...

  3. hdu 4992 Primitive Roots 【求原根模板】

    题目链接 大题流程: 判定是否有原根->求出最小原根->利用最小原根找出全部原根 #include<bits/stdc++.h> using namespace std; ty ...

  4. luogu P6091 原根

    LINK:原根 再复习一下原根 防止考场上要NTT求原根的时候不会求... 这道题要求求出n之内的所有原根 根据原根的定义. 原根指 若x对于模n的阶为phi(n)且\(1\leq x\leq n\) ...

  5. 多项式FFT相关模板

    自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h& ...

  6. uestc_retarded 模板

    虽然这个队,以后再也没有了,但是他的模板,是永垂不朽的![误 #include <ext/pb_ds/priority_queue.hpp> __gnu_pbds::priority_qu ...

  7. 多项式细节梳理&模板(多项式)

    基础 很久以前的多项式总结 现在的码风又变了... FFT和NTT的板子 typedef complex<double> C; const double PI=acos(-1); void ...

  8. 数论算法 剩余系相关 学习笔记 (基础回顾,(ex)CRT,(ex)lucas,(ex)BSGS,原根与指标入门,高次剩余,Miller_Rabin+Pollard_Rho)

    注:转载本文须标明出处. 原文链接https://www.cnblogs.com/zhouzhendong/p/Number-theory.html 数论算法 剩余系相关 学习笔记 (基础回顾,(ex ...

  9. FFT/NTT总结+洛谷P3803 【模板】多项式乘法(FFT)(FFT/NTT)

    前言 众所周知,这两个东西都是用来算多项式乘法的. 对于这种常人思维难以理解的东西,就少些理解,多背板子吧! 因此只总结一下思路和代码,什么概念和推式子就靠巨佬们吧 推荐自为风月马前卒巨佬的概念和定理 ...

  10. NTT模板

    NTT(快速数论变换)用到的各种素数及原根: https://blog.csdn.net/hnust_xx/article/details/76572828 NTT多项式乘法模板 #include&l ...

随机推荐

  1. wpf 富文本编辑器richtextbox的简单用法

    最近弄得一个小软件,需要用到富文本编辑器,richtextbox,一开始以为是和文本框一样的用法,但是实践起来碰壁之后才知道并不简单. richtextbox 类似于Word,是一个可编辑的控件.结构 ...

  2. long ? 的使用和理解

    Dictionary<string, object> dic = new Dictionary<string, object>(); long lg = 12345; dic[ ...

  3. 前端 | 页面触底自动加载 Vue 组件

    不管是 web 端还是移动端,信息流都是现在很流行的信息展示方式.信息流经常搭配自动加载一起使用以获得更好的使用体验. 最近在使用 Vue 开发过程中也遇到了首页信息流自动加载的需求.大致了解了一下几 ...

  4. 项目版本管理Git使用详细教程

    前言 记得刚开始做项目开发的时候都是一个人完成一个项目,单打独斗的开发,也不知道什么是团队开发,没有这个概念,随着工作后来知道公司里项目都是团队开发,这个时候这么多人怎么开发一个项目呢,难道用u盘拷贝 ...

  5. Element form表单方法resetFields无效

    之前遇到resetFields无效时都是自己手动用this.ruleForm = Object.assign({}, this.ruleForm, this.$options.data().ruleF ...

  6. ES6扩展运算符(三点运算符)...的用法

    1. 第一个叫做 展开运算符(spread operator),作用是和字面意思一样,就是把东西展开.可以用在array和object上都行. let a = [1,2,3]; let b = [0, ...

  7. MySQL——MySQL初始化配置文件

    初始化配置文件(影响服务器和客户端程序) 1.MySQL初始化配置加载顺序: 命令行 ----> 初始化配置文件 ----> 预编译选项 2.MySQL初始化配置文件加载顺序: (1)/e ...

  8. 一个简单的URL访问权限校验

    前言 目前最流行的两大安全框架:SpringSecruity.Shiro 权限控制,无非就是:前端控件是否可见.是否允许请求/访问URL 本文分享一个简单的URL访问权限校验,支持/./*./**等情 ...

  9. Postman调试Abp API

    在swagger中查看登录需要用post方式访问,Abp需要用application/json方式调用 请求体 Postman调用方式 例:访问所有用户,调用Api地址为http://localhos ...

  10. ABP 极简入门教程(三 权限)

    此处演示为MVC项目,同样权限定义需要到Application中才能在获取API时进行权限验证 一.打开Sample.Core\Authorization\PermissionNames.cs增加授权 ...