Love you Ten thousand years(求原根个数+欧拉函数+原根定理)

Love you Ten thousand years

 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,(n is a odd prime number) is a LovePoint-based-on n if and only if the set { (x i mod n) | 1 <= i <= n-1 } is equal to { 1, ..., n-1 }. For example, the powers of 3 modulo 7 are 3, 2, 6, 4, 5, 1, and thus 3 is a LovePoint-based-on 7.
Now give you a integer n >= 3(n will not exceed 2 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 n. Input is terminated by the end-of-file.
Output
For each n, print a single number that gives the number of days someone loved you.
Sample Input

5

Sample Output

2
题意:

让我们求出小于n的数的个数,满足 ki mod n,1in k i   m o d   n , 1 ≤ i ≤ n 是模n的完全剩余系

其实就是让我们求一个数n的原根个数

分析:

为什么是求原根的个数呢?原根又是什么呢?

这要从头说起。。。


如果a与p互质,费马小定理告诉我们

ap11 (mod p) a p − 1 ≡ 1   ( m o d   p )

当然对于a来说,有可能存在多个i满足 1ip1,ai1 (mod p) 1 ≤ i ≤ p − 1 , a i ≡ 1   ( m o d   p )

这样一来就一定可以存在一个最小的幂次e使得 ae1 (mod p) a e ≡ 1   ( m o d   p )

我们定义这个最小指数叫a模p的次数或阶

ep(a)=使ae1 (mod p)e1 e p ( a ) = ( 使 得 a e ≡ 1   ( m o d   p ) 的 最 小 指 数 e ≥ 1 )

那么就一定会存在这样的一个a ( 1ap1 1 ≤ a ≤ p − 1

ep(a)=p1 e p ( a ) = p − 1

我们就称这样的a为模p的原根

对于原根a来说他的幂

a,a2,a3,a4,.....ap3,ap2,ap1 (mod p) a , a 2 , a 3 , a 4 , . . . . . a p − 3 , a p − 2 , a p − 1   ( m o d   p )

必须都是模p不同的(既然p-1个数模p都不同那么值一定是1,2,3….p-1了)

证明:

假设有两个模p后值相同的我们取幂次 i,j,1i<jp1 i , j , 1 ≤ i < j ≤ p − 1
aiaj (mod p) a i ≡ a j   ( m o d   p )
两边同乘 aj a j 的逆元
aji1 (mod p) a j − i ≡ 1   ( m o d   p )
其中指数 ji j − i 一定小于 p1 p − 1
矛盾,故命题得证

原根定理:

每个素数p都有原根,有恰好 ϕ(p1) ϕ ( p − 1 ) 个模p的原根

对于一般情况所有的数m来说并不一定有原根,但当模m有原根时,可以其原根个数为 ϕ(ϕ(m)) ϕ ( ϕ ( m ) )

(和费马小定理推广为欧拉定理类似)

以上均为现成的定理,这里不再一一证明,以后会专门证明这些定理

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int Euler(int n){
    int ans = n;
    for(int i = 2; i * i <= n; i++){
        if(n % i == 0){
            ans = ans / i * (i - 1);
            while(n % i == 0) n /= i;
        }
    }
    if(n > 1) ans = ans / n * (n - 1);
    return ans;
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        printf("%d\n",Euler(Euler(n)));
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值