• 原根二连 HDU 4992 && poj 1284 Primitive Roots


    原根存在的充要条件
      n = 1,2,4,p^r (p为奇素数,r为任意正整数)

    原根的性质

        若n存在原根,则原根个数为φ(φ(n))

        若g是n的一个原根,则g^d是n的原根的充要条件为gcd(d,φ(n)) = 1
        一个数的全体原根乘积模n余1
        一个数的全体原根和模n余μ(n-1)
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    bool isprime[1000001];
    LL prime[100001];
    LL primesize = 0,n,ans[10001],p;
    LL res[1000005];
    LL gcd(LL a,LL b){
      if (b == 0) return a;
      return gcd(b,a % b);
    }
    
    LL Fast_Mod(LL a,LL b,LL p){
       LL res = 1,base = a;
       while (b){
           if (b&1) res = (res*base) % p;
           base = (base*base) % p;
           b = b >> 1;
       }
       return res;
    }
    
    void initPrime(){
      memset(isprime,1,sizeof(isprime));
      isprime[1] = false;
      LL ListSize = 1000000;
      for (LL i=2;i<= ListSize ; i++){
        if (isprime[i]) {
          primesize ++; prime[primesize] = i;
        }
        for (int j=1;j<=primesize && i*prime[j] <= ListSize; j++){
          isprime[i*prime[j]] = false;
          if (i % prime[j] == 0) break;
        }
     }
    }
    
    LL phi(LL n){
        LL i,rea=n;
        for(i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                rea=rea-rea/i;
                while(n%i==0)  n/=i;
            }
        }
        if(n>1)
            rea=rea-rea/n;
        return rea;
    }
    
    bool exist(LL n){
      if (n % 2 == 0) n /= 2;
      if (isprime[n]) return 1;
      for (int i=3;i*i<=n;i+=2){
        if (n % i == 0){
          while (n % i == 0) n /= i;
          return (n == 1);
        }
      }
      return 0;
    }
    
    int main()
    {
        // freopen("test.in","r",stdin);
        initPrime();
        while(scanf("%lld",&p)!=-1)
        {
            int cnt=0;
            if (p == 2) {
              cout << 1 << endl; continue;
            }
            if (p == 4){
              cout << 3 << endl; continue;
            }
            if (!exist(p)){
              cout << -1 << endl; continue;
            }
            n = phi(p);
            for(int i=1;i<=primesize&&prime[i]*prime[i]<=n;i++)
            {
                if(n%prime[i]==0)
                {
                    n/=prime[i];
                    cnt ++;
                    ans[cnt]=prime[i];
                    while(n%prime[i]==0)
                    {
                        n/=prime[i];
                    }
                }
            }
            if(n!=1){
              cnt ++;
              ans[cnt]=n;
            }
            n = phi(p);
            LL g;
            for (int i=2;i<p;i++){
              if (gcd(i,p) == 1){
                int ok = 1;
                for (int j=1;j<=cnt;j++){
                  if (Fast_Mod(i,n/ans[j],p) == 1){
                    ok = 0; break;
                  }
                }
                if (ok){
                    g = i;
                    break;
                }
              }
            }
            LL total = 0;
            for (int i=1;i<=n;i++){
              if (gcd(i,n) == 1){
                total ++;
                res[total] = Fast_Mod(g,i,p);
              }
            }
            sort(res+1,res+total+1);
            for (int i=1;i<=total-1;i++){
              cout << res[i] << " ";
            }
            cout << res[total] << endl;
        }
    
        return 0;
    }
    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long LL;
    bool isprime[1000001];
    LL prime[100001];
    LL primesize = 0,n,ans[10001],p;
    
    LL gcd(LL a,LL b){
      if (b == 0) return a;
      return gcd(b,a % b);
    }
    
    LL Fast_Mod(LL a,LL b,LL p){
       LL res = 1,base = a;
       while (b){
           if (b&1) res = (res*base) % p;
           base = (base*base) % p;
           b = b >> 1;
       }
       return res;
    }
    
    void initPrime(){
      memset(isprime,1,sizeof(isprime));
      isprime[1] = false;
      LL ListSize = 1000000;
      for (LL i=2;i<= ListSize ; i++){
        if (isprime[i]) {
          primesize ++; prime[primesize] = i;
        }
        for (int j=1;j<=primesize && i*prime[j] <= ListSize; j++){
          isprime[i*prime[j]] = false;
          if (i % prime[j] == 0) break;
        }
     }
    }
    
    LL phi(LL n){
        LL i,rea=n;
        for(i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                rea=rea-rea/i;
                while(n%i==0)  n/=i;
            }
        }
        if(n>1)
            rea=rea-rea/n;
        return rea;
    }
    
    int main()
    {
        // freopen("test.in","r",stdin);
        initPrime();
        while(scanf("%lld",&p)!=-1)
        {
            int cnt=0;
            n = phi(p);
            for(int i=1;i<=primesize&&prime[i]*prime[i]<=n;i++)
            {
                if(n%prime[i]==0)
                {
                    n/=prime[i];
                    cnt ++;
                    ans[cnt]=prime[i];
                    while(n%prime[i]==0)
                    {
                        n/=prime[i];
                    }
                }
            }
            if(n!=1){
              cnt ++;
              ans[cnt]=n;
            }
            bool find = 0;
            n = phi(p);
            for (int i=2;i<p;i++){
              if (gcd(i,p) == 1){
                int ok = 1;
                for (int j=1;j<=cnt;j++){
                  if (Fast_Mod(i,n/ans[j],p) == 1){
                    ok = 0; break;
                  }
                }
                if (ok){
                  find = 1; break;
                }
              }
            }
            if (find){
              cout << phi(phi(p)) << endl;
            }
            else {
              cout << 0 << endl;
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    VC++中使用内存映射文件处理大文件
    802.1x协议解析
    Jscript中window.setInterval和window.setTimeout区别
    在C#中使用代理的方式触发事件
    JavaScript实用的一些技巧
    控制C#编的程序内存的占用
    纯C#钩子实现及应用(转)
    DES的建立过程
    C# 显示占用内存
    解决“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”
  • 原文地址:https://www.cnblogs.com/ToTOrz/p/7413669.html
Copyright © 2020-2023  润新知