zoukankan      html  css  js  c++  java
  • 原根

    原根以前没学懂,今天重新学了一下。
    19.07.02update:忘了,又重新学了一下。
    19.07.09update:耶我记住了。


    定义
    先引出阶的定义:
    ((a, n) = 1),则满足(a^r equiv 1 (mod n))的最小整数(r),称为(a)(n)的阶。
    首先(r)是显然存在的,因为根据费马小定理,有(a ^ {varphi(n)} equiv 1 (mod n)),那么(r leqslant varphi(n))
    (r = varphi(n))的时候,称(a)为模(n)的一个原根。


    性质
    对于原根(g)(g ^ 0, g ^ 1, g ^ 2 ldots g ^ {p - 2})恰好与([1, p - 1])一一对应。在[SDOI2015]序列统计这道题上有妙用。


    求法
    暴力的求法:
    因为原根一般比较小,所以从2开始枚举,然后对于每一个枚举的(g),再从(1)(varphi(n) - 1)枚举(i),根据定义,若(g ^ i equiv 1 (mod n)),那么(g)就不是原根。
    改进:
    实际上没必要枚举所有(i),只要枚举(varphi(n))的因数即可。
    即如果对于所有的(i (i | varphi(n)))都有(g ^ i otequiv 1 (mod n)),必然对于任意一个(j (j otmid varphi(n))),都有(g ^ j otequiv 1 (mod n))
    证明:原根--zhouyuheng2003


    于是代码就很好写了
    51nod上竟然有例题:原根

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    //const int maxn = ;
    inline ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    inline void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    
    In ll quickpow(ll a, ll b, ll mod)
    {
      ll ret = 1;
      for(; b; b >>= 1, a = a * a % mod)
        if(b & 1) ret = ret * a % mod;
      return ret;
    }
    In ll phi(ll n)
    {
      ll ret = n; 
      for(int i = 2; i * i <= n; ++i)
        {
          if(n % i) continue;
          ret = ret / i * (i - 1);
          while(n % i == 0) n /= i;
        }
      if(n > 1) ret = ret / n * (n - 1);
      return ret;
    }
    
    int p[1000], pcnt = 0;
    In ll G(ll m)
    {
      ll Phi = phi(m);
      pcnt = 0;
      for(int i = 2; i * i <= Phi; ++i) 
        if(Phi % i == 0)
    	{
    	  p[++pcnt] = i;
    	  if(Phi / i != i) p[++pcnt] = Phi / i;
    	}
      for(int g = 2; g <= Phi; ++g)
        {
          bool flg = 1;
          if(quickpow(g, Phi, m) ^ 1) continue;
          for(int i = 1; i <= pcnt && flg; ++i)
    	    if(quickpow(g, p[i], m) == 1) flg = 0;
          if(flg) return g;
        }
    }
    
    int main()
    {
      ll m = read();
      write(G(m)), enter;
      return 0;
    }
    
  • 相关阅读:
    2019年中国高校计算机大赛
    2019年华北五省(市、自治区)及港澳台大学生计算机应用大赛
    2019年(第12届)中国大学生计算机设计大赛
    2020移动开发竞赛
    2019年华北五省(市、自治区)及港澳台大学生计算机应用大赛
    Android 开发者指南
    Android :HangUp Notification 横幅通知
    HBU E-mobile
    Android Q is Android 10
    Android Studio 3.5(Last updated 7/29/2019)
  • 原文地址:https://www.cnblogs.com/mrclr/p/10742576.html
Copyright © 2011-2022 走看看