zoukankan      html  css  js  c++  java
  • 51nod 1135 原根 (数论)

    题目链接

    建议与上一篇欧拉函数介绍结合食用。

    知识点:
    1.阶:a和模m互质,使a^d≡1(mod m)成立的最小正整数d称为a对模m的阶(指数)
       例如:
      2^2≡1(mod3),2对模3的阶为2;
      2^3≡1(mod7),2对模7的阶为3;
    2.欧拉函数φ(m):在[1,m)的区间内与m互质的数的个数。可见前一篇blog
    3.设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。

    求模素数p的原根a的方法:

    对质数 p, φ(p) = p-1, 这题就是要找最小的a使得 a^(p-1)%p = 1 成立(根据费马小定理,该式一定成立,且a可取大于 1 的任意整数),所以只需要验证没有比 p-1 小的数 k 令 a^k%p = 1 。

    而 k 不需要全部枚举 ,只需枚举 p-1 除去1和它本身的质因子即可。(如果x为p-1的质因子,且a^x%p = 1,那么x的倍数nx显然也满足a^nx%p = 1 ,所以没必要考虑了。反之同理。)

    所以重点就到回到了找质因子上,1e9,还是筛。

    参考了很多dalao的博客,但链接没记下来,不好意思。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define maxn 50000
     5 using namespace std;
     6 typedef long long ll;
     7 int prime [maxn];//存素数
     8 int ppri [maxn];//存p-1的质因子
     9 void getprime(){//打表
    10     int cnt = 0;
    11     memset(prime,0,sizeof(prime));
    12     for(int i=2;i<maxn;i++){
    13         if(!prime[i]) prime[++cnt]=i;//如果没被标记过,就是质数
    14         for(int j=i;j<maxn;j+=i) prime[j] = 1;//此质数的倍数都标记为1
    15     }
    16 }
    17 ll pow(ll x,ll n,ll mod){//快速幂
    18     ll res=1;
    19     while(n>0){
    20         if(n%2) res=res*x%mod;
    21         x=x*x%mod;
    22         n/=2;
    23     }
    24     return res;
    25 }
    26 
    27 int divide(int n){//分解n的质因子
    28     int cnt=0;
    29     for(int i = 1; prime[i] * prime[i] <= n; ++i){
    30         if(n % prime[i] == 0)  ppri[++cnt]=prime[i];
    31         while(n % prime[i] == 0)  n/=prime[i];
    32     }
    33     return cnt;
    34 }
    35 
    36 int main(){
    37     int p,a,t,flag,cnt;
    38     cin>>p;
    39     getprime();
    40     cnt=divide(p-1);//p-1 的质因子个数
    41     for(a = 2; a <= p - 1; ++a){//a 从 2 到 p-1 枚举
    42         flag=1;
    43         for(int i=1; i <= cnt; ++i){
    44             t = (p - 1) / ppri[i];
    45             if(pow(a, t, p)==1){
    46                 flag=0;
    47                 break;
    48             }
    49         }
    50         if(flag){
    51             cout<<a<<endl;
    52             break;
    53         }
    54     }
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    [团队项目]典型用户
    0415 操作系统_实验二、作业调度模拟程序
    0415 结对2.0评价
    复利计算- 结对2.0--复利计算WEB升级版
    0408汉堡
    复利计算- 结对1.0
    0405《构建之法》第四章读后感
    复利计算器4.0 【java版】
    复利计算器的单元测试结果
    操作系统 实验一、命令解释程序的编写实验
  • 原文地址:https://www.cnblogs.com/noobimp/p/10296364.html
Copyright © 2011-2022 走看看