zoukankan      html  css  js  c++  java
  • 找新朋友

    来源

    http://139.196.145.92/contest_show.php?cid=1890#problem/C

    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
    
    前置知识:
    1. Elur函数

      对于正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目.如:(varphi (8)=4),为1,3,5,7

      性质:

      • 若p为质数,显然(varphi(p)=p-1)
      • (p=a^b(a,b,p in N^*))(a为质数),(varphi(p)=a^b-a^{(b-1)}=(a-1)*a^{(b-1)}),因为一共有(n=a^b)个数,想要获得所有与n互质的数,只需要除去a的倍数即可.这里简单地解释一下(a^{(b-1)}):设有n中有m个a的倍数,则有(ma=a^b => m=a^{(b-1)}).
      • Elur函数是积性函数,即:(varphi(mn)=varphi(m)*varphi(n)(m,n互质))

      (p=a_1^{b_1}*a_2^{b_2}*a_3^{b_3}...(a_i为质数{p,a_i,b_i|p,a_i,b_i in N^*})),由算术基本定理可知,这里的p可以表示所有的正整数.那么,根据以上三条性质可得:

      [varphi(p)=(a_1-1)*(a_2-1)*(a_3-1)...a_1^{(b_1-1)}*a_2^{(b_2-1)}*a_3^{(b_3-1)}... ]

    分析问题:
    1. 显然只要套一下公式即可
    代码:
    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    ll getNum(ll n);
    
    int main()
    {
        ll n,num,ans;
        scanf("%lld",&num);
        while(num--){
            scanf("%lld",&n);
            ans = getNum(n);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    ll getNum(ll n) //计算n中的
    {
        ll num=1;
        for(int i=2;i*i<=n;i++){  //相等的时候也需要包含在内,否则出来的时候只加一次
            if(n%i==0){  //这个内外的乘法参考了晚上的代码,很巧妙,没有对于a^(i-1)次做额外的判断
                n/=i;
                num*=(i-1);  //这里乘了a
                while(n%i==0){  //设n=i^a+j,这边乘了a-1次
                    n/=i;
                    num*=i;
                }
            }
        }
        if(n>1){
            num*=n-1;
        }
        return num;
    }
    

    注:

    • 这边的质数i的遍历是从2开始依次向上遍历的,但合数,如:4不会影响到结果,因为n已经被质数2筛过了
    • wa了两发,都是因为i*i<n,因为如果没有包括i*i=n的范围,那么最后的num*=n-1,有时应该是num*=(n-1)*n
  • 相关阅读:
    MSN无法登录(错误代码80072745)的解决方法
    C#3.0新体验(二) 扩展方法
    My DreamTech
    让IE崩溃的bug, IE8也一样崩溃
    多线程的相关概念
    10条PHP经验总结
    PHP框架 CI与TP之MVC比较
    多线程设计要点
    Linux yum命令的使用技巧
    BigPipe 的工作原理
  • 原文地址:https://www.cnblogs.com/Arno-vc/p/13722545.html
Copyright © 2011-2022 走看看