快速求原根的实现

关于原根是什么以及这里的求法

http://www.cnblogs.com/linkzijun/p/6380486.html

在末尾可以看到我之前写的定义和求法以及求法的证明。。很巧妙。。

设要求原根的质数为P,这个算法的复杂度大概是O(P-1)*log(P-1),后面是P-1不同质因子的数量

(学习了下tls for的写法。。结果结尾忘了写分号。。崩了一次,囧

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int maxn=1e6+7;
bool not_pr[maxn];int pr[maxn],sz,fac[maxn],fz,P;
typedef long long ll;
void Sieve(){
    int i,j;
    for(i=2;i<maxn;++i){
        if(!not_pr[i]) pr[sz++]=i;
        for(j=0;j<sz&&i*pr[j]<maxn;++j){
            not_pr[i*pr[j]]=1;
            if(i%pr[j]==0) break;
        }
    }
}
void factor(int p){
    fz=0;int tmp=p-1,i;
    for(i=0;i<sz;++i){
        if(tmp==1) break;
        if(tmp%pr[i]==0){
            for(tmp/=pr[i];tmp%pr[i]==0;tmp/=pr[i]);    //这里是分号
            fac[fz++]=pr[i];
        }
    }
    if(tmp!=1) fac[fz++]=tmp;
}
ll mod_pow(ll a,ll b,ll p){
    if(b==0) return 1;
    ll ans=1;
    while(b){
        if(b&1) ans=(ans*a)%p;
        a=(a*a)%p;
        b>>=1;
    }
    return ans;
}
bool judge(int x){
    int i;
    for(i=0;i<fz;++i){
        if(mod_pow(x,(P-1)/fac[i],P)==1) return false;
    }
    return true;
}
int main(){
    Sieve();
    while(~scanf("%d",&P)){
        factor(P);
        for(int i=2;;++i) if(judge(i)) {printf("%d\n",i);break;}
    }
    return 0;
}
时间: 2024-08-10 12:19:41

快速求原根的实现的相关文章

快速求原根

当需要求质数\(P\)的原根\(G\),只需枚举\(a \in [2,P - 1]\),检验对\(P - 1\)的所有质因子\(p_i\),\(a^{\frac{P - 1}{p_I}} \mod P\)是否等于\(0\),若都不等于\(0\),则\(a\)为\(P\)的原根 51Nod原根 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include&l

非递归快速求幂算法

快速求正整数次幂,当然不能直接死乘.举个例子:3 ^ 999 = 3 * 3 * 3 * … * 3直接乘要做998次乘法.但事实上可以这样做,先求出2^k次幂:3 ^ 2 = 3 * 33 ^ 4 = (3 ^ 2) * (3 ^ 2)3 ^ 8 = (3 ^ 4) * (3 ^ 4)3 ^ 16 = (3 ^ 8) * (3 ^ 8)3 ^ 32 = (3 ^ 16) * (3 ^ 16)3 ^ 64 = (3 ^ 32) * (3 ^ 32)3 ^ 128 = (3 ^ 64) * (3

A sequence of numbers(快速求幂)

题目描述 Xinlv wrote some sequences on the paper a long time ago, they might be arithmetic or geometric sequences. The numbers are not very clear now, and only the first three numbers of each sequence are recognizable. Xinlv wants to know some numbers in

NYOJ--102--次方求模(快速求幂取模)

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 1 /* 2 Name: NYOJ--102--次方求模 3 Copyright: ?

快速求幂

快速幂在算指数时是很高效的,他的基本原理是二进制. 如果要算 2^5,可以直接2*2*2*2*2 但是如果要算 3^999,指数N太大,计算太慢,所以有一种快速的解法. @@@@@@@@@@@@@@@@@@@@@@@@ 以3^21为例. 2^21=(2^16)×(2^4)×(2^1) 21的二进制可以写成(10101)----------------而10101可以写成1*2^4+0*2^3+1*2^2+0*2^1+1*2^0 可以明显看出, 每一个香对应着上边的指数.   2^4=16 2^2

Quick-Select 1亿个数快速求第K小的数 分治法

Quick-Select  1亿个数快速求第K小的数  分治法 利用快速排序的思想,一开始选取中枢元,然后左右调整,接着比对中枢元p和K的大小,如果 p+1 = k (数组从0开始), 那么a[p] 就是答案,因为在p之前的,肯定都是小于a[p]的, 在p之后的,肯定大于p, 所以 a[p] 就是第 p+1 小.假如 p+1 不等于K, 那么根据大小,进行左右调整.调整过程中,理想状态下,每次都砍掉一半,数组的起始坐标要进行调整. 代码: // 快速排序法的修改 #include <iostre

POJ2478_Farey Sequence【快速求欧拉函数】

Farey Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12377 Accepted: 4808 Description The Farey Sequence Fn for any integer n with n >= 2 is the set of irreducible rational numbers a/b with 0 < a < b <= n and gcd(a,b) = 1

快速求幂运算笔记

如何快速求x得n次方呢? 首先C++里面有个pow如何实现呢?自己查查,里面使用double,肯定更麻烦,还有jianzhi 我们会顺手写下 int res=1; for(int i=1;i<=n;i++) { res*=x; } 学习一下快速幂,logn内计算出来,使用N的二进制,只需要logN就可以计算. 正要的就是计算每个为1对应的基数.列入: 11是多少?是二进制的话,就是1*2^1+1 那么x^(11)呢,两个1对应的基数是多少呢?低位1对应的是X,高位1对应的是X^2,因此,就是位于

【GDOI 2011 DAY2 T3】零什么的最讨厌了 (快速求阶乘、中国剩余定理)

问题描述: 林记在做数学习题的时候,经常遇到这种情况:苦思冥想了很久终于把问题解出来,结果发现答案是0,久而久之林记在得到习题答案是0的时候就没有了做出一道难题的成就感.于是林记决定:以后出题,答案一定不能是0,例如求n!最低位非零数这样的习题就很不错了. 现在林记提出了一个更难一点的问题:求n!在K进制下的最低位非零数.其中K符合一些特殊的条件:K是由若干个互不相同的质数相乘得出来的,例如K=2,3,5,6,7,10…… 输入格式: 首先输入的第一行是一个整数Q,表示询问的个数. 接下来是Q个