hdoj 1286 找新朋友 (欧拉函数)

找新朋友

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5518    Accepted Submission(s): 2842

链接: http://acm.hdu.edu.cn/showproblem.php?pid=1286

Problem Description
 
  新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。
 
Input
  第一行是测试数据的组数CN(Case number,1<CN<10000),接着有CN行正整数N(1<n<32768),表示会员人数。
 
Output
  对于每一个N,输出一行新朋友的人数,这样共有CN行输出。
 
Sample Input
2
25608
24027
 
Sample Output
7680
16016
 
解题思路:
  此题是关于欧拉函数的简单数论题,首先我们先来看看欧拉函数(也称 φ函数):
  
          欧拉函数: 对于给定正整数 n ,少于或等于n的数中与n互质的数的数目。
            若n是质数p的i次幂,φ(n)=p^i - p^(i-1)=(p-1)*p^(i-1) (解题关键),因为除了p的倍数外,其他数都跟n互质。
            设n为正整数,以 φ(n)表示不超过n且与n互素的正整数的个数,称为n的欧拉函数值,这里函数
              φ:N→N,n→φ(n) 称为欧拉函数。
           欧拉函数是积性函数——若m,n互质,φ(mn)=φ(m)φ(n) [积性函数的形式]。
           特殊性质:当n为奇数时,φ(2n)=φ(n), 证明与上述类似
    
  根据欧拉函数,对于给定的 n ,我们总能找到小于 n 的(当 n 为素数时, 等于 n )素数 p1, p2, ··· , pN, 使得
        n = (p1 ^ a1) * (p2 ^ a2) * ···· * (pN ^ aN);
      所以,
        φ(n)=φ(p1 ^ a1) * φ(p2 ^ a2) * ··· * φ(pN ^ aN)
       所以,
        φ(n) = ((p1 - 1)* p1^(a1 - 1)) * ((p2 - 1)* p2^(a2 - 1)) * ··· * ((pN - 1)* pN^(aN - 1))
     
  
  首先,我们假设与 n 互质的数(小于 n ) 有 n 个, 事实上它有 φ(n) 个, 我们可以寻找 n 与 φ(n) 的关系来求解:
         n / φ(n) = (p1 * p2 * ··· * pN) / ((p1-1) * (p2-1) * ··· *(pN-1))
     所以,
        φ(n) = (n * (p1-1) * (p2-1) * ··· *(pN-1)) / (p1 * p2 * ··· * pN);
      即:
        φ(n) = n * ((p1-1) / p1) * ((p2-1) / p2) * ··· * ((pN-1) / pN);
 
AC代码:
 1 #include<iostream>
 2 #include<cmath>
 3 
 4 using namespace std;
 5 
 6 int Euler(int n);
 7 
 8 int main()
 9 {
10     int cn, n, num;
11     cin >> cn;
12     while(cn--)
13     {
14         cin >> n;
15         num = Euler(n);
16         cout << num << endl;
17     }
18     return 0;
19 }
20 
21 int Euler(int n)
22 {
23     int num, i;
24     num = n;
25     for(i = 2; i < (int)sqrt(n*1.0)+1; ++i)
26     {
27         if(!(n % i )) {
28             num = num/i *(i-1);
29             while(!(n % i))
30                 n /= i;
31         }
32     }
33     if(n > 1)
34         num = num/n * (n-1);
35     return num;
36 }

 

  

转载于:https://www.cnblogs.com/Duahanlang/archive/2013/05/02/3055454.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值