1. 程式人生 > >poj 1284 Primitive Roots 【原根】【數論】

poj 1284 Primitive Roots 【原根】【數論】

題目連結 : 傳送門

題目大意: 求一個質數的原根個數。

先普及一下原根的定義:

設m是正整數,a是整數,若a模m的階等於euler(m),則稱a為模m的一個原根。

eg: m=7,euler(7) =  6(1,2,3,4,5,6)  

則:

  • 1   1^(n)mod7=1! = 6
  • 2   2^(n)mod7={2 4 1}!=6 
  • 3   3^(n)mod7={3,2,6,4,5,1}==6   故3是模7的原根
  • 4   4^(n)mod7={4,2,1}!=6
  • 5   5^(n)mod7={5,4,6,2,3,1}==6   故5是模7的原根
  • 6   6^(n)mod7={6,1}!=6    
故7的原根有兩個。 也可以這樣來想: a^(p-1)mod(p)=1,(p-1)為最小的使得 a^(x) mod (1)  = 1  滿足的x。 判斷方法:判斷g^(m-1) = 1 (mod m)是否當且當指數為m-1的時候成立 m有原根的充要條件是m= 1,2,4,p,2p,p^n,其中p是奇質數,n是任意正整數 有一個規律,任何一個質數的原根個數都是等於euler(n-1)的值。 則本題的程式碼如下:
#include<iostream>
#include<stdio.h>
using namespace std;
//直接求解尤拉函式,返回euler(n)
int euler(int n){
     int res=n,a=n;
     for(int i=2;i*i<=a;i++)
     {
         if(a%i==0)
         {
             res=res/i*(i-1);   //先進行除法是為了防止中間資料的溢位
             while(a%i==0) a/=i;
         }
     }
     if(a>1) res=res/a*(a-1);
     return res;
}


int main ()
{
  int num;
  while(~scanf("%d",&num))
  {
      printf("%d\n",euler(num-1));
  }
}