• SGU[102] Coprimes


    Description

    描述

    For given integer N (1<=N<=10^4) find amount of positive numbers not greater than N that coprime with N. Let us call two positive integers (say, A and B, for example) coprime if (and only if) their greatest common divisor is 1. (i.e. A and B are coprime iff gcd(A,B) = 1).

    对于给定的整数N(1<=N<=10^4)求不大于N并且与N互素的正整数的个数。我们称两个正整数(例如A、B)互素,但且仅当它们的最大公约数为1。(即gcd(A,B)=1)

     

    Input

    输入

    Input file contains integer N.

    输入文件包含整数N。


    Output

    输出

    Write answer in output file.

    将答案输出在输出文件上。


    Sample Input

    样例输入

    9


    Sample Output

    样例输出

    6

     

    Analysis

    分析

    我首先想到的是欧拉函数(varphileft(N ight)),后来发现数据量并不是特别的大,所以又用暴力做了一遍,也AC了。

     

    这道题目的重点在于欧拉函数(varphileft(N ight))的求法,现总结如下:

    欧拉函数(varphileft(N ight)):小于等于N且与N互素的正整数的个数。

    欧拉函数据有如下性质:

    • (varphi left ( 1 ight )=1)

    • (varphi left ( N ight )=Ncdotprod_{p|N}{left (frac{p-1}{p}   ight )}),其中(p)为素数

    • (varphi left ( p^{k} ight ) = p^{k}-p^{k-1}=left(p-1 ight )cdot p^{k-1}),其中(p)为素数

    • (varphi left ( mn ight )=varphi left ( m ight )cdot varphi left ( n ight )),其中(gcd{left ( m,n ight )}=1)

    根据第2个式子我们就可以求出欧拉函数。

    基本思路:首先置(varphileft(N ight)=N),然后枚举(N)的素因子(p),将(p)的整数倍的欧拉函数(varphi left ( kcdot p ight ))置(varphi left ( kcdot p ight )=varphi left ( kcdot p ight )cdotleft (frac{p-1}{p}   ight ))即可。

    基本代码如下:

    #include <iostream>
    
    using namespace std;
    
    const int MAX = 1024;
    
    int N;
    int p[MAX], phi[MAX];
    
    int main()
    {
        cin >> N;
        for(int i = 1; i <= N; i++)	// 初始化
        { p[i] = 1; phi[i] = i; }
        p[1] = 0;	// 1不是素数
        for(int i = 2; i <= N; i++)	// 筛素数
        {
            if(p[i])
            {
                for(int j = i * i; j <= N; j += i)
                { p[j] = 0; }
            }
        }
        for(int i = 2; i <= N; i++)	// 求欧拉函数
        {
            if(p[i])
            {
                for(int j = i; j <= N; j += i)	// 处理素因子p[i]
                {
                    phi[j] = phi[j] / i * (i - 1);	// 先除后乘,防止中间过程超出范围
                }
            }
        }
        cout << "Primes: " << endl;
        for(int i = 1; i <= N; i++)
        { if(p[i]) { cout << i << " "; } }
        cout << endl;
        cout << "Euler Phi Function: " << endl;
        for(int i = 1; i <= N; i++)
        { cout << phi[i] << " "; }
        return 0;
    }
    

    Solution

    解决方案

    欧拉函数:

    #include <iostream>
    #include <math.h>
    #include <stdio.h>
    
    using namespace std;
    
    int phi(int x);
    
    int main()
    {
    	int N;
    	cin >> N;
    	cout << phi(N) << endl;
    	cout << endl;
    	return 0;
    }
    
    int phi(int x)
    {
    	int nRet = x;
    	int nTmp = (int)sqrt(x);
    	for(int i = 2; i <= nTmp; i++)
    	{
    		if(x % i == 0)
    		{
    			nRet = nRet / i * (i - 1);
    			while(x % i == 0)
    			{ x /= i; }
    		}
    	}
    	if(x > 1)
    	{
    		nRet = nRet / x * (x - 1);
    	}
    	return nRet;
    }

    暴力:

    #include <iostream>
    #include <math.h>
    #include <stdio.h> 
    
    using namespace std;
    
    int gcd(int x, int y);
    
    int main()
    {
    	int N, nRet = 0;
    	cin >> N;
    	for(int i = 1; i <= N; i++)
    	{
    		if(gcd(N, i) == 1)
    		{ nRet++; }
    	}
    	cout << nRet << endl;
    	return 0;
    }
    
    int gcd(int x, int y)
    {
    	if(y == 0) { return x; }
    	return gcd(y, x % y);
    }

     

    SGU不愧是经典题目的合集,每做一道题都会学到一些新的东西。

  • 相关阅读:
    Python界面常用GUI包
    ATSC/DVB/ISDB三大标准比较
    【MPEG】DVB / ATSC / ISDB区别
    Python判断字符串是否为字母或者数字
    MApp_ZUI_CTL_MarqueeTextWinProc字串滚动
    PWM原理及其在电源中的应用
    按键板的原理与实现 扩展GPIO
    按键板的原理与实现----ADC
    使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
    SQL Server备份还原数据库中的小把戏
  • 原文地址:https://www.cnblogs.com/Ivy-End/p/4260799.html
Copyright © 2020-2023  润新知