HDU 2619 - Love you Ten thousand years (原根)

时光总嘲笑我的痴心妄想 提交于 2019-12-22 05:02:26

Description:

Love you Ten thousand years------Earth’s rotation is a day that is the representative of a day I love you. True love, there is no limit and no defects. Earth’s revolution once a year, it is on behalf of my love you more than a year. Permanent horizon, and my heart will never change ……

We say that integer x,0<x<n,x, 0 < x < n,(nn is a odd prime number) is a LovePoint-based-on n if and only if the set (ximodn)1<=i<=n1{ (x i mod n) | 1 <= i <= n-1 } is equal to 1,...,n1{ 1, ..., n-1 }. For example, the powers of 33 modulo 77 are 3,2,6,4,5,13, 2, 6, 4, 5, 1, and thus 33 is a LovePoint-based-on 77.
Now give you a integer n>=3n >= 3(nn will not exceed 2312 31).
We say the number of LovePoint-based-on n is the number of days the earth rotating.
Your task is to calculate the number of days someone loved you.

Input

Each line of the input contains an integer nn. Input is terminated by the end-of-file.

Output

For each nn, print a single number that gives the number of days someone loved you.

Sample Input

5

Sample Output

2

求有多少i(<=n1)i(<=n-1),使 ximod  nx^i \mod n 的值为 [1,n1][1,n-1],其实也就是满足完全剩余类的原根数量。

m>1m > 1gcd(a,m)=1gcd(a, m) = 1, 则使得 at1(modm)a^t ≡ 1(mod m) 成立的最小的正整数 tt 称为 aa 对模mm的阶, 记为δm(a)δm(a)

如果 aa的阶(modm)(mod m)ϕ(m)ϕ(m), 则称 aamm 的一个原根。 即若 δm(a)=ϕ(m)δm(a)=ϕ(m), 则称aamm 的一个原根。

定理1:若 ggmm 的一个原根,则 g,g2,,gϕ(m)g,g^2,⋯,g^ϕ(m)

各数对模 mm 的最小剩余,恰是小于 mm 且与 mm 互素的 ϕ(m)ϕ(m) 个正整数的一个排列。

定理2:每一个素数 pp 都有 ϕ(p1)ϕ(p−1) 个原根。ϕ(m)ϕ(m) 为小于mm 的素数的个数,事实上, 每一个数 mm 都有 ϕ(ϕ(m))ϕ(ϕ(m)) 个原根(如果有的话)。即 若 nn 为素数 ϕ(p1)=ϕ(ϕ(p))ϕ(p−1) = ϕ(ϕ(p))

这个题中 nn 为奇素数,故形成的为完全剩余系。求 nn 的原根数量即可。

AC代码:

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stack>
#include <queue>
using namespace std;
#define sd(n) scanf("%d", &n)
#define sdd(n, m) scanf("%d%d", &n, &m)
#define sddd(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define pd(n) printf("%d\n", n)
#define pc(n) printf("%c", n)
#define pdd(n, m) printf("%d %d", n, m)
#define pld(n) printf("%lld\n", n)
#define pldd(n, m) printf("%lld %lld\n", n, m)
#define sld(n) scanf("%lld", &n)
#define sldd(n, m) scanf("%lld%lld", &n, &m)
#define slddd(n, m, k) scanf("%lld%lld%lld", &n, &m, &k)
#define sf(n) scanf("%lf", &n)
#define sc(n) scanf("%c", &n)
#define sff(n, m) scanf("%lf%lf", &n, &m)
#define sfff(n, m, k) scanf("%lf%lf%lf", &n, &m, &k)
#define ss(str) scanf("%s", str)
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define mem(a, n) memset(a, n, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define mod(x) ((x) % MOD)
#define gcd(a, b) __gcd(a, b)
#define lowbit(x) (x & -x)
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
inline int read()
{
    int ret = 0, sgn = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            sgn = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        ret = ret * 10 + ch - '0';
        ch = getchar();
    }
    return ret * sgn;
}
inline void Out(int a)
{
    if (a > 9)
        Out(a / 10);
    putchar(a % 10 + '0');
}

ll gcd(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}

ll lcm(ll a, ll b)
{
    return a * b / gcd(a, b);
}
///快速幂m^k%mod
ll qpow(int m, int k, int mod)
{
    ll res = 1, t = m;
    while (k)
    {
        if (k & 1)
            res = res * t % mod;
        t = t * t % mod;
        k >>= 1;
    }
    return res;
}

// 快速幂求逆元
int Fermat(int a, int p) //费马求a关于b的逆元
{
    return qpow(a, p - 2, p);
}

///扩展欧几里得
int exgcd(int a, int b, int &x, int &y)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int g = exgcd(b, a % b, x, y);
    int t = x;
    x = y;
    y = t - a / b * y;
    return g;
}

///使用ecgcd求a的逆元x
int mod_reverse(int a, int p)
{
    int d, x, y;
    d = exgcd(a, p, x, y);
    if (d == 1)
        return (x % p + p) % p;
    else
        return -1;
}

///中国剩余定理模板
ll china(int a[], int b[], int n) //a[]为除数,b[]为余数
{
    int M = 1, y, x = 0;
    for (int i = 0; i < n; ++i) //算出它们累乘的结果
        M *= a[i];
    for (int i = 0; i < n; ++i)
    {
        int w = M / a[i];
        int tx = 0;
        int t = exgcd(w, a[i], tx, y); //计算逆元
        x = (x + w * (b[i] / t) * x) % M;
    }
    return (x + M) % M;
}

ll phi(ll n)
{
    ll ans = n;
    for (int i = 2; i * i <= n; i++)
    {
        if (n % i == 0)
        {
            ans -= ans / i;//素数倍数的个数减去
            while (n % i == 0)
                n /= i;//除去素数倍数
        }
    }
    if (n > 1)//对素数特判
        ans -= ans / n;
    return ans;
}//互素数的个数

ll n, m;
int main()
{
    while (~sld(n))
    {
        pld(phi(phi(n)));
    }
    return 0;
}




标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!