1. 程式人生 > >HDU 4992 Primitive Roots(求出n的所有原根)

HDU 4992 Primitive Roots(求出n的所有原根)

題意:求出n的所有原根,不存在原根輸出-1。

原根的定義題目已經給出,對於n的原根x,則滿足x的y次冪模n等於1的最小y是n的尤拉函式值phi(n),也就是小於等於n且與n互質的個數。

官方的題解裡面說暴力求出一個原根來,然後利用結論:

如果g是模m的原根,整數d>=0,則g的d次冪是模m的原根的一個充要條件是d和phi(m)互質。d暴力列舉即可。

然後我就傻傻跑去暴力求原根,,,TLE。。。

然後查了下維基百科才發現還有其他性質可以用。

一個是如果gcd(g, m)=1,且g^d=1(mod m),則d為phi(m)的一個因子。換句話說如果g是m的原根,那麼對於phi(m)的所有因子d(不包含phi(m)本身),g^d=1(mod m)是不成立的。我們可以通過列舉phi(m)的質因子以及g^phi(m)=1(mod m)是否成立來判斷g是否是模m的原根。

然後有些不存在原根的數字利用另一條性質排除:

模m有原根的充要條件是m=2,4,p^n, 2p^n,p為奇質數,n任意正整數。

如果m沒有滿足上述條件,就直接輸出-1。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1000000;
bool f[N];
int phi(int x){
    if(f[x])    return x-1;
    int ans = x;
    for(int i=2; i<=x; i++){
        if(x%i==0){
            while(x%i==0)   x/=i;
            ans = ans - ans/i;
        }
    }
    if(x>1) ans = ans - ans/x;
    return ans;
}
int gcd(int a, int b){
    swap(a,b);
    int c = a%b;
    while(c){
        a=b; b=c; c=a%b;
    }
    return b;
}
int quick_mod(int x, int p, int mod){
    long long s = 1;
    long long a = x;
    while(p){
        if(p&1) s = (s*a)%mod;
        a = a*a%mod;
        p>>=1;
    }
    return (int)s;
}
vector<int> V;
vector<int> G;
void cal(int x){
    G.clear();
    if(f[x])    return;
    else{
        for(int i=2; i*i<=x; i++){
            if(x%i==0){
                G.push_back(i);
                if(i*i!=x)  G.push_back(x/i);
            }
        }
    }
}
bool exist(int n){
    if(n%2==0)  n/=2;
    if(f[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;
}
void solve(int n){
    if(n==2){
        puts("1");
        return;
    }
    if(n==4){
        puts("3");
        return;
    }
    if(!exist(n)){
        puts("-1");
        return;
    }
    int p = phi(n);
    cal(p);
    int x = -1;
    for(int i=2; i<n; i++){
        bool flag = 1;
        if(quick_mod(i, p, n)!=1)   continue;
        for(int j=0; j<G.size(); j++){
            if(quick_mod(i, G[j], n)==1){
                flag = 0;
                break;
            }
        }
        if(flag){
            V.resize(1);
            V[0] = x = i;
            break;
        }
    }
    if(x==-1){
        puts("-1");
        return;
    }
    for(int i=2; i<p; i++){
        if(gcd(i, p)==1)    V.push_back(quick_mod(x, i, n));
    }
    sort(V.begin(), V.end());
    vector<int>::iterator it=unique(V.begin(), V.end());
    V.erase(it, V.end());
    for(int i=0; i<V.size(); i++){
        if(i)   putchar(' ');
        printf("%d", V[i]);
    }
    puts("");
}
int main(){
    memset(f, 1, sizeof(f));
    f[0] = f[1] = 0;
    for(int i=2; i<N; i++){
        if(f[i]){
            for(int j=i<<1; j<N; j+=i)  f[j]=0;
        }
    }
    int n;
    while(~scanf("%d", &n)) solve(n);
    return 0;
}


相關推薦

HDU 4992 Primitive Rootsn所有

題意:求出n的所有原根,不存在原根輸出-1。 原根的定義題目已經給出,對於n的原根x,則滿足x的y次冪模n等於1的最小y是n的尤拉函式值phi(n),也就是小於等於n且與n互質的個數。 官方的題解裡面說暴力求出一個原根來,然後利用結論: 如果g是模m的原根,整數d>

HDU 4992 Primitive Roots 數論-

題意很簡單:求所有原根,那麼問題來了,何為原根?設 (a,m)=1, 滿足 ax≡1(modm) 的最小的 x,稱為a對m的階,記為 ordm(a)當 ordm(a)=ϕ(m) 時稱為a為m的原根.原根有什麼性質能幫助解這道題?1.n有原根⇔n=2,4,pe,2pe(p為奇素

HDU 4992 Primitive Roots ()

Primitive Roots Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 949    Accepted

LightOJ - 1117 Helping Cicada 1~n有多少個數不能被這m個數中任意一個整除(容斥+狀態壓縮)

vol == show fine cst href main http color 題意:http://www.lightoj.com/volume_showproblem.php?problem=1117 考慮1個數k,1~n有[n/k]個數能被k整除,[a]表示a向下取

快速n!的質因數的個數

font 如果 數組 code -s 組合數 cnblogs 每一個 bsp 一般做組合數的題目都要進行質因數的分解,我們一般是for循環對每個數進行質因數分解,大多數情況都不會超時,但極少數的情況下,題目會不允許這樣的做法,所以我們需要學會一種更快的方法來求質因數。 我

Dijkstra--POJ 2502 Subway所有路徑再最短路徑

題意: 你從家往學校趕,可以用步行和乘坐地鐵這兩種方式,步行速度為10km/h,乘坐地鐵的速度為40KM/h。輸入資料的第一行資料會給你起點和終點的x和y的座標。然後會給你數目不超過200的雙向地鐵線路的站點,你可以從一個站點乘坐地鐵到下一個站點,你可以在同一線

【LeetCode】Longest Common Subsequence最長公共子序列某一解+LCS長度

Longest Common Subsequence 給出兩個字串,找到最長公共子序列(LCS),返回LCS的長度。 說明 最長公共子序列的定義: • 最長公共子序列問題是在一組序列(通常2個)中找到最長公共子序列(注意:不同於子串,LCS不需要是

HDU-6318 Swaps and Inversions逆序數+樹狀陣列

Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth

最長迴文序列最長的並且打印出來

這兩道題都是求最長迴文的長度,在這裡我已開始想著就是沒有思路,想了半天,然後翻了會兒書,找到了一個知識點,那就是manacher演算法 這個演算法很好的解決了這道難題,然後我子啊百度上邊找啊找,找

POJ 1284:Primitive Roots素數的個數

Primitive Roots Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5709 Accepted: 3261 Description We say that integer x,

尤拉函式n互質的數的個數

求解與n(1-n-1)互質的質因子的個數 解析:(轉) 定義:對於正整數n,φ(n)是小於或等於n的正整數中,與n互質的數的數目。     例如:φ(8)=4,因為1,3,5,7均和8互質。 性質:1.若p是質數,φ(p)= p-1. 2.若n是質數p的k

POJ 2992C(n,k)的約數個數

首先肯定不可能一個一個進行計算 採用數論中的相關知識可以得到求解本題的兩個公式, 對於任於的數p=n1p1∗n2p2∗n3p3.....p=n1p1∗n2p2∗n3p3..... p的因數個數為(1+p1)∗(1+p2)∗(1+p3)....(1+p1)

素數篩選法 1~n的素數

1、下面是求1~n的素數的一般方法: //求1~n的素數一般方法 #include<iostream> using namespace std; int main() { int n,i,j,k=1; bool bo; cin>>n

2^x mod n = 1 HDU - 1395歐拉定理

tex sub tar define pair sam %d tps col 2^x mod n = 1 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

HDU 1198 Farm Irrigation 並查集優化,構圖

++ space int con can 組成 union trac 輸入 本題和HDU暢通project類似。僅僅只是暢通project給出了數的連通關系, 而此題須要自己推斷連通關系,即兩個水管能否夠連接到一起,也是本題的難點所在。 記錄狀態。不斷combine()

HDU 1846 Brave Game巴什博弈超簡單題

sca space == div 法則 由於 out con 希望 題目傳送:http://acm.hdu.edu.cn/showproblem.php?pid=1846 Problem Description 十年前讀大學的時候,中國每年都要從國外引進一些電影大片,其中有

HDU 6044--Limited Permutation搜索+組合數+逆元

name review cst pri getchar value ane ips begin 題目鏈接 Problem Description As to a permutation p1,p2,?,pn from 1 to n, it is uncomplic

POJ3107Godfather樹的重心裸題

i++ got cte tun set can contains ctu fort Last years Chicago was full of gangster fights and strange murders. The chief of the police g

vue實現一個會員卡的組件(可以動態傳入圖片的一個組件、背景、文字、卡號等)

less flow BE star efault client component ali adding 自己在寫這個組件的時候主要遇到的問題就是在動態傳入背景圖片或者背景色的時候沒能立馬順利寫出來,不過現在實現了這個簡單組件就和大家分享一下 <template&g

leetcode-350-Intersection of Two Arrays II兩個數組的交集

CA 更新 lse write limited elements 表示 app 順序 題目描述: Given two arrays, write a function to compute their intersection. Example:Given nums1 =