• HDU 4910 Problem about GCD 找规律+大素数判断+分解因子


    Problem about GCD

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 470    Accepted Submission(s): 77


    Problem Description
    Given integer m. Find multiplication of all 1<=a<=m such gcd(a, m)=1 (coprime with m) modulo m.
     
    Input
    Input contains multiple tests, one test per line.
    Last line contains -1, it should be skipped.

    [Technical Specification]
    m <= 10^18
     
    Output
    For each test please output result. One case per line. Less than 160 test cases.
     
    Sample Input
    1
    2
    3
    4
    5
    -1
     
    Sample Output
    0
    1
    2
    3
    4
    Source
     
    打表找规律:
    数字n 如果由 x^k组成  或者 2*y^k 组成(x,y不等于2了,k为1,2,3,....) 则结果为n-1;
    否则为1.
     
    思路:
    1.特判%4的情况。
    2.m = n  , 如果m为偶数先除2 。
    3.如果m本身就是素数 m = m^1 ,那就是n-1了。
    4.如果m由两个素数组成 m = x*x ,x是素数. 也简单,开平方,然后判断是不是素数。
    5.如果m由多个素数组成 m = x^k,那么这个素数一定在10^6里面出现。
      至少为3次吧。
    代码很挫。
      1 #include<iostream>
      2 #include<stdio.h>
      3 #include<cstring>
      4 #include<stdlib.h>
      5 #include<time.h>
      6 #include<math.h>
      7 using namespace std;
      8 typedef __int64 LL;
      9 const int maxn = 1e6+1;
     10 int prime[maxn],len;
     11 bool s[maxn];
     12 
     13 void init()
     14 {
     15     int i,j;
     16     len = 0;
     17     memset(s,true,sizeof(s));
     18     s[1] = false;
     19     for(i=2;i<maxn;i++)
     20     {
     21         if(s[i] == false) continue;
     22         prime[++len] = i;
     23         for(j=i*2;j<maxn;j=j+i)
     24             s[j] = false;
     25     }
     26 }
     27 //****************************************************************
     28 // Miller_Rabin 算法进行素数测试
     29 //速度快,而且可以判断 <2^63的数
     30 //****************************************************************
     31 const int S=20;//随机算法判定次数,S越大,判错概率越小
     32 LL mult_mod(LL a,LL b,LL mod) //(a*b)%c a,b,c<2^63
     33 {
     34     a%=mod;
     35     b%=mod;
     36     LL ans=0;
     37     while(b)
     38     {
     39         if(b&1)
     40         {
     41             ans=ans+a;
     42             if(ans>=mod)
     43             ans=ans-mod;
     44         }
     45         a=a<<1;
     46         if(a>=mod) a=a-mod;
     47         b=b>>1;
     48     }
     49     return ans;
     50 }
     51 LL pow_mod(LL a,LL b,LL mod) // a^b%mod
     52 {
     53     LL ans=1;
     54     a=a%mod;
     55     while(b)
     56     {
     57         if(b&1)
     58         {
     59             ans=mult_mod(ans,a,mod);
     60         }
     61         a=mult_mod(a,a,mod);
     62         b=b>>1;
     63     }
     64     return ans;
     65 }
     66 
     67 //以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数
     68 //一定是合数返回true,不一定返回false
     69 
     70 bool check(LL a,LL n,LL x,LL t)
     71 {
     72     LL ret=pow_mod(a,x,n);
     73     LL last=ret;
     74     for(int i=1;i<=t;i++)
     75     {
     76         ret=mult_mod(ret,ret,n);
     77         if(ret==1 && last!=1 && last!=n-1) return true;//合数
     78         last=ret;
     79     }
     80     if(ret!=1) return true;
     81     else return false;
     82 }
     83 
     84 // Miller_Rabin()算法素数判定
     85 //是素数返回true.(可能是伪素数,但概率极小)
     86 //合数返回false;
     87 
     88 bool Miller_Rabin(LL n)
     89 {
     90     if(n<2)return false;
     91     if(n==2) return true;
     92     if( (n&1)==0) return false;//偶数
     93     LL x=n-1;
     94     LL t=0;
     95     while( (x&1)==0 ) { x>>=1;t++;}
     96     for(int i=0;i<S;i++)
     97     {
     98         LL a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
     99         if(check(a,n,x,t))
    100         return false;//合数
    101     }
    102     return true;
    103 }
    104 bool Euler(LL n)
    105 {
    106     LL i , knum = 0;
    107     for(i=1;prime[i]<=n&&i<=len;i++)
    108     {
    109         if(n%prime[i]==0)
    110         {
    111             while(n%prime[i]==0)
    112                 n=n/prime[i];
    113             knum++;
    114         }
    115         if(knum>=2) break;
    116     }
    117     if(knum == 1 && n==1) return true;
    118     /**此处为n == 1 不是n == 0**/
    119     return false;
    120 }
    121 void solve(LL n,LL m)
    122 {
    123     if( (m<=1000000 && s[m] == true) || Miller_Rabin(m) == true)
    124     {
    125         printf("%I64d
    ",n-1);
    126         return;
    127     }
    128     LL k = (LL)sqrt(m*1.0);
    129     if(k * k == m && Miller_Rabin(k) == true)
    130     {
    131         printf("%I64d
    ",n-1);
    132         return;
    133     }
    134     if(Euler(m)==true)
    135     {
    136         printf("%I64d
    ",n-1);
    137         return;
    138     }
    139     printf("1
    ");
    140 }
    141 int main()
    142 {
    143     init();
    144     LL n , m;
    145     while(scanf("%I64d",&n)>0)
    146     {
    147         if(n==-1) break;
    148         if(n<=5){
    149             printf("%I64d
    ",n-1);
    150             continue;
    151         }
    152         m = n;
    153         if( (m&1) == 0)
    154         {
    155             m = m /2;
    156             if((m&1)==0)
    157             {
    158                 printf("1
    ");
    159                 continue;
    160             }
    161         }
    162         solve(n,m);
    163     }
    164     return 0;
    165 }
  • 相关阅读:
    「Codeforces 79D」Password
    「算法笔记」BSGS
    「Codeforces 468C」Hack it!
    「算法笔记」快速傅里叶变换(FFT)
    「算法笔记」2-SAT 问题
    「算法笔记」基础数论 2
    《算法笔记》二分—木棒切割问题&求凸多边形外接圆最大半径
    《算法笔记》区间贪心
    《算法笔记》PAT B1020 月饼、PAT B1023 组个最小数
    《算法笔记》n皇后问题
  • 原文地址:https://www.cnblogs.com/tom987690183/p/3900270.html
Copyright © 2020-2023  润新知