1. 程式人生 > >Jzoj P3520 原根___列舉

Jzoj P3520 原根___列舉

題目大意:

在這裡插入圖片描述 給出一個mm,求出它的所有原根,不存在輸出1-1m10000m ≤ 10000

分析:

n=p1c1p2c2..pxcxn={p_1}^{c1}{p2}^{c2}..{p_x}^{c_x} 則有φ(n)=n(11p1)(11p2)..(11px)φ(n)=n(1-\frac{1}{p1})(1-\frac{1}{p2})..(1-\frac{1}{p_x}) 然後直接求出來φ(m)φ(m) 然後列舉[1,m][1,m]暴力判斷是否是原根即可 時間複雜度:O

(mφ(m))O(mφ(m))

程式碼:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define N 10005

using namespace std;

int prime[N], a[N], n, phi, cmt;

int Gcd(int x, int y)
{
	if (x < y) swap(x, y);
	while (1)
	{
	   int r = x % y;
	   x = y, y = r;	
       if (r == 0) break;
	}
	return x;
}

int main()
{
	freopen("math.in", "r", stdin);
	freopen("math.out", "w", stdout);
	scanf("%d", &n);
	phi = n, cmt = n;
	for (int i = 2; i * i <= n; i++)
		if (cmt % i == 0) 
		{
		    phi = phi - phi / i;
		    while (cmt % i == 0) cmt /= i;
        }
    if (cmt > 1) phi = phi - phi / cmt;
	bool dop = 1; 
    for (int i = 1; i <= n; i++)
	{
        if (Gcd(i, n) != 1) continue;     
        bool flag = 0; int gg = 1;
		for (int j = 1; j < phi; j++)
		{
			gg = gg * i % n;
			if (gg == 1) { flag = 1; break; }
		}
		if (!flag) { dop = 0; printf("%d\n", i); }
    }
    if (dop) printf("-1\n");
	return 0;
}