首页 > 其他分享 >【学习笔记】原根

【学习笔记】原根

时间:2023-04-25 09:58:43浏览次数:59  
标签:phi return 原根 int 笔记 学习 ansn mod

原根是 \(NTT\) 的前置,想学 \(NTT\) 就得先学求原根。
由于作者个人时间原因,原根直接讲结论。

 
只有\(2,4,p^c,2\times p^c\)有原根,其中 \(c\) 为奇质数。
\(n\) 的原根大概在 \(n^{0.25}\) 左右,且分布密集。
检测 \(p\) 是否是原根,要看对于所有的 \(\phi(n)\) 的质数 \(k\),是否都有 \(p^{\frac{\phi(n)}{k}} != 1\)。(理解是除了 \(p^{\phi(n)}\) 其他的次方都不能等于1)
找到最小原根 \(p\) 后(复杂度 \(n^{0.25} \log{\phi(n)}\)),可以通过 \(p^k\) \((gcd(k,\phi(n))==1)\) 求出所有的原根。原根总个数为 \(\phi(\phi(n))\)。

 
luogu模板题代码。

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=10000010,Ma=1e6;
int mod;
int wk[N],zhi[N],tail;
int n,d,fi,ans[N],cnt;
int sum[N],tot;
bool had[N];
int gcd(int x,int y){return (!y)?x:gcd(y,x%y);}
int pw(int x,int y){
	int ansn=1;
	while(y){
		if(y&1)ansn=ansn*x%mod;
		x=x*x%mod,y/=2;
	}
	return ansn;
}
void work(){
	n=rd(),d=rd(),cnt=tot=0;
	if(!had[n])return printf("0\n\n"),void();
	mod=n;
	fi=n;
	for(int i=1;i<=tail&&zhi[i]<=n;i++)if(n%zhi[i]==0)fi=fi*(zhi[i]-1)/zhi[i];
	for(int i=1;i<=tail&&zhi[i]<=fi;i++)if(fi%zhi[i]==0)sum[++tot]=zhi[i];
	int gen;
	for(gen=1;gen<n;gen++){
		if(gcd(gen,n)!=1)continue;
		bool flg=true;
		for(int i=1;i<=tot;i++){
			if(pw(gen,fi/sum[i])==1)flg=false;
		}
		if(flg)break;
	}
	for(int i=1,j=gen;i<=fi;i++,j=j*gen%mod){
		if(gcd(i,fi)==1)ans[++cnt]=j;
	}
	sort(ans+1,ans+cnt+1);
	printf("%lld\n",cnt);
	for(int i=d;i<=cnt;i+=d)printf("%d ",ans[i]);
	printf("\n");
	return ;
}
signed main(){
	for(int i=2;i<=Ma;i++){
		if(!wk[i])zhi[++tail]=i;
		for(int j=1;j<=tail&&i*zhi[j]<=Ma;j++){
			wk[zhi[j]*i]=true;
			if(i%zhi[j]==0)break;
		}
	}
	had[2]=had[4]=true;
	for(int i=2;i<=tail;i++){
		for(int j=1;j*zhi[i]<=Ma;j=j*zhi[i])had[j*zhi[i]]=true;
		for(int j=2;j*zhi[i]<=Ma;j=j*zhi[i])had[j*zhi[i]]=true;
	}
	int T=rd();
	while(T--)work();
	return 0;
}
/*
1
36 1
*/

标签:phi,return,原根,int,笔记,学习,ansn,mod
From: https://www.cnblogs.com/flywatre/p/17351704.html

相关文章

  • 迁移学习(MEnsA)《MEnsA: Mix-up Ensemble Average for Unsupervised Multi Target Doma
    论文信息论文标题:MEnsA:Mix-upEnsembleAverageforUnsupervisedMultiTargetDomainAdaptationon3DPointClouds论文作者:AshishSinha,JonghyunChoi论文来源:2023 CVPR论文地址:download 论文代码:download视屏讲解:click1前言单目标域和多目标域2介绍单......
  • GIT 学习记录
    gitinit--bare git初始化服务器仓库gitinit 初始化本地仓库gitadd. 本地仓库添加gitcommit-m"firstversion" 本地仓库首次提交===本地仓库关联服务器远程仓库===gitremoteaddoriginhttps://github.com/xxxx/frp.git或者gitremoteaddoriginname@192......
  • 怎么用手机记笔记?安卓手机超实用的笔记app
    都已经到2023年了,现在还有人随着携带纸质笔记本来记笔记吗?与纸质笔记本相比,手机笔记APP上不仅支持用户添加文字、图片、视频等多种格式的文件随手做笔记,而且更加便于修改、保存、删除、分享等,可以提高大家使用笔记的效率。那么怎么用手机记笔记呢?安卓手机超实用的笔记app是哪款?其......
  • 学习MASA第一天:MASA Blazor TEST项目创建
    个人博客地址:https://note.raokun.top拥抱ChatGPT,国内访问网站:https://www.playchat.top学习MASA第一天:MASABlazorTEST项目创建从今天开始,学习MASA框架,目标是基于MASA做一套开源项目。第一天,从下载源码开始![443684122256924]我们今天先把框架源码下载下来,以便后面每天......
  • 李航统计学习概述
    监督学习感知机概念:感知机模型的基本形式是:\(f(x)=sign(w\cdotx+b)\)其中,\(x\)是输入样本的特征向量,\(w\)是权值向量,\(b\)是偏置量,\(w\cdotx\)表示向量\(w\)和\(x\)的点积。\(sign\)函数表示符号函数,当输入大于0时输出1,否则输出-1。要求模型必......
  • 建个随笔记录版本
    因式分解模拟器2.0*修复了两个式子前后互换位置无法识别的错误*增加了正确答案存在时间*整体难度下调*修改了难度的选择部分,更加简洁*增加了很多注释https://files.cnblogs.com/files/blogs/777644/%E5%9B%A0%E5%BC%8F%E5%88%86%E8%A7%A3%E6%A8%A1%E6%8B%9F%E5%99%A82.0.zip?t=1......
  • 人月神话阅读笔记06
    继续干将莫邪看到这个阅读题目,一般不会将他跟编程的阅读笔记联系起来,但是,这个模块主要讲述的是资源的合理利用,其中也包含着“工欲善其事,必先利其器”的道理;主要强调了合理的资源利用更有助于项目的完成,较好的编程方法(也可以是更适合自己的方法),更加有利于项目的实现与完成!整体......
  • 【多臂赌机】基于时变egreedy策略结合强化学习求解多臂赌机问题附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • JavaSE笔记——02
    Java流程控制仅仅个人学习记录,不涉及任何商用1.用户交互Scanner从JDK1.5版本之后,专门提供了输入数据类Scanner,此类数据不但可以输入数据,而且也能方便地验证输入的数据。->1.Scanner类概述​ Scanner类可以接收任意的输入流。Scanner类放在java.util包中,其常用的方法......
  • JavaSE笔记——03
    Java方法仅仅个人学习历程记录,不涉及任何商用方法1.方法的定义:一段用来完成特定功能的代码片段,类似于其他语言的函数。2.方法的作用:用于定义该类或该类的实例的行为特征和功能实现3.区别:​ 面向过程中,函数是最基本的单位,整个程序都是由一个个程序组成的​ 面向对象......