正题

题目链接: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. The requested PHP extension ext-http * is missing from your system. Install or enable PHP's http ex

    composer.json 包含 "require": { "ext-http": "*" } 删掉  "ext-http&quo ...

  2. WebAPI 自定义过滤

    自定义filter 类过滤 ------------------------------------------------------------------------- public class ...

  3. 【java web】过滤器、拦截器、监听器的区别

    一.对比: 1.1 过滤器和拦截器的区别: ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对actio ...

  4. spring的异常处理

    出自于:https://blog.csdn.net/he90227/article/details/46309297   ---- 利用Spring进行统一异常处理的两种方式. 原文:https:// ...

  5. js对url进行编码和解码

    编码 只有 0-9[a-Z] $ - _ . + ! * ' ( ) , 以及某些保留字,才能不经过编码直接用于 URL. 例如:搜索的中文关键字,复制网址之后再粘贴就会发现该URL已经被转码. 1. ...

  6. Python - 面向对象编程 - 什么是 Python 类、类对象、实例对象

    什么是对象和类 https://www.cnblogs.com/poloyy/p/15178423.html Python 类 类定义语法 最简单的类定义看起来像这样 class ClassName: ...

  7. windows安装trojan记录

    1.trojan 客户端安装教程 https://v2raytech.com/trojan-clients/ 2.chrome安装插件(crx文件)教程 https://www.jianshu.com ...

  8. Spring Boot +Vue 项目实战笔记(一):使用 CLI 搭建 Vue.js 项目

    前言 从这篇文章开始,就进入真正的实践了. 在前端项目开发中,我们可以根据实际情况不同程度地使用 Vue.利用 Vue CLI(或写成 vue-cli,即 Vue 脚手架)搭建出来的项目,是最能体现 ...

  9. Kickstart部署多系统

    原文转自:https://www.cnblogs.com/itzgr/p/10029587.html作者:木二 目录 一 准备 1.1 完整架构:Kickstart+DHCP+HTTP+TFTP+PX ...

  10. MySQL主库手动复制至从库

    原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 主库手动复制至从库 1.1 Master主库锁表 1.2 主库备份 1.3 从 ...