51nod1135(求最小原根)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1135

题意:中文题诶~

思路:设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数)给出1个质数P,找出P最小的原根。

我们先了解一下阶的概念:满足 a^r Ξ (1 mod m) ---1 的最小 r 即为 a%m的阶,我们可以直接从小到大枚举a, 然后将 r= φ(m) 带入进去,

判断如果满足  1式(即 a^x%m=1当且仅当 x=r 时成立)的话即为我们所求的答案。又因为输入的 m为质数,所以 r= φ(m)=m-1.

判断对于当前 a,x=m-1 是否是 a^x%m=1---2 成立的唯一解我们不可能直接从正面枚举每个x,因为我们并不知道是否存在一个数 n, x>n时2式一定不成立,也就是我们不能确定枚举 x 的范围,那么枚举 x 也就无从谈起咯。不过还有有这样一个定理 对 (m-1) 只因分解成 m1, m2, m3....mk,若存在 x=(m-1)/mi 使得式2成立,那么

当前 a 不是 a mod m 的原根。所以我们就可以从反面枚举 x 啦,若当前 a 使得 x=(m-1)/mi (1<=i<=k)对于式2都不满足, 那么当前 a 即为所求解啦~

代码:

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 #define MAXN 100
 4 using namespace std;
 5
 6 ll prime[MAXN];
 7 int cnt=0;
 8
 9 void make_prime(ll x){
10     for(int i=2; i*i<=x; i++){
11         if(x%i==0){
12             prime[cnt++]=i;
13             while(x%i==0){
14                 x/=i;
15             }
16         }
17     }
18     if(x>1){
19         prime[cnt++]=x;
20     }
21 }
22
23 ll get_pow(ll x, int n, int mod){
24     ll ans=1;
25     while(n){
26         if(n&1){
27             ans=ans*x%mod;
28         }
29         x=x*x%mod;
30         n>>=1;
31     }
32     if(ans<0){
33         ans+=mod;
34     }
35     return ans;
36 }
37
38 int main(void){
39     ll m;
40     scanf("%lld", &m);
41     make_prime(m-1);
42     for(int i=2; i<m; i++){
43         int flag=1;
44         for(int j=0; j<cnt; j++){
45             int x=(m-1)/prime[j];
46             if(get_pow(i, x, m)==1){
47                 flag=0;
48                 break;
49             }
50         }
51         if(flag){
52             printf("%d\n", i);
53             return 0;
54         }
55     }
56     return 0;
57 }
时间: 2024-10-10 21:18:51

51nod1135(求最小原根)的相关文章

求最小原根 51nod 1135

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1135 代码 // the smallest primitive root of prime P #include <bits/stdc++.h> const long long mod = 1e9+7; const double ex = 1e-10; #define inf 0x3f3f3f3f using namespace std; long long N; i

HDU4992 求所有原根

Primitive Roots Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 583    Accepted Submission(s): 144 Problem Description We say that integer x, 0 < x < n, is a primitive root modulo n if and only

HDU 3035 War(对偶图求最小割)

HDU 3035 War 题目链接 题意:根据图那样,给定一个网络,要求阻断s到t,需要炸边的最小代价 思路:显然的最小割,但是也显然的直接建图强行网络流会超时,这题要利用平面图求最小割的方法,把每一块当成一个点,共有边连边,然后每一个路径就是一个割,然后最短路就是最小割了 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace s

hdu 3746 Cyclic Nacklace (KMP求最小循环节)

//len-next[len]为最小循环节的长度 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; char a[100010]; int next[100010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len) { if(j==-1||a[i]==a[j]) i

LeetCode -- Triangle 路径求最小和( 动态规划问题)

人们常说"细节决定成败". 编码工作中,同样需要关注细节. 本文将给出3个小实例来说明编码中关注细节的重要性,同时给出作者对如何注意编码细节的一点见解(说的不对,请指正). 例1 这个问题如此地显而易见,竟然没有被发现. List<int> numList = new List<int>(); numList.Add(3); numList.Add(1); numList.Add(4); numList.Add(2); numList.Add(5); numLi

hiho 第116周,最大流最小割定理,求最小割集S,T

#include <bits/stdc++.h> using namespace std; #define maxn 505 #define INF 0x3f3f3f3f struct Edge { int from,to,cap,flow; }; struct Dinic { int n,m,s,t; vector<Edge> edge; vector<int> G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn];

BZOJ_1001_狼抓兔子(平面图求最小割+对偶图求最短路)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1001 分析 平面图求最小割,转化成对偶图求最短路,经典. 注意: 1.优先队列是个大根堆. 2.Dijkstra可以带一个vis数组,也可以不带,因为一个点出来以后,它更新的的点和原本就在队列里的点都比它大,所以它不可能被更新得更小,之后这个点再出队时情况不比第一次更优,所以出队也不会有操作. 3.双向边,数组要开够(貌似不是第一次犯这个错误). 4.网上有人说m==1||n==1的情况可以

hdu 3987 求最小割条数最小

题意:    一个人要从起点  0  到达 n-1   n个点  m条路  ,我们求最少破坏路的条数使无法 从起点到达终点.题意很明显  ,求最小割条数最少,由于最小割流量虽然固定,但是其条数却不固定,可以破坏3条路,也可以破坏4条路,他们总流量相同才会出现这种情况. 题解:由于上述的情况,他们总流量相同但是条数不同,现在我们需要改变边的容量使得条数少边才是最小割,条数多的将不会是最小割. 官方题解有两种 ,我选择的是在残余网络中进行扩充流的操作,使的两个最小割不同,残余网络中,我进行所有边流量

HDU1394 线段树求最小逆序数

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1394 求最小的逆序数,在此贴下逆序数的概念: 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数.逆序数为偶数的排列称为偶排列:逆序数为奇数的排列称为奇排列.如2431中,21,43,41,31是逆序,逆序数是4,为偶排列. 也是就说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规