• pku 1142 Smith Number


    /*
    Author: JackWang
    Date: 01-10-10 20:20
    Description: 
    求Smith数,Smith数的所有因数的数字之和等于自己的数字之和
    例子:
    
    本题中,质数不算Smith数
    
    解题思路:
    因为要因式分解,所以要算质数,而且要存储从2开始的一些质数,方便分解计算。
    算质数用筛法计算。 
    质数要算多少是一个问题,题目保证最大的数是100,000,000以内,在32位int之内。
    但是用筛法算100,000,000内的所有质数是耗时很长的,因此只能算一部分。其余部分直接用简单判别法判断。 
    简单判别法:判断它是否能整除小于等于它平方根的数,如果能整除,就不是质数,如果都不能整除则它是质数。
    因此,计算100,000,000的因数只需要sqrt(10,000,000) = 10,000以内的数即可,因此筛法计算10,000个质数即可。
    */
    
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    const int N = 1000000;          // 筛法中的最大判断数量
    const int P = 78498;            // 在N的范围内质数的数量
    const int MAX_PRIME = 999983;   // 在N的范围内最大的质数
    char isPrime[N];                // 筛法中是否是质数的布尔向量,0为质数1为合数
    int primeNumbers[P];            // 按顺序从小到大的N范围内的所有质数
    int primeDigitSum[P];           // 与所有质数相对应的数量和,primeNumbers[i]的数量和 = primeDigitSum[i]
    
    // 计算一个正整数的各个数字之和。
    int sumDigits(int n) {
    	int sum = 0;
    	while (n > 0) {
    		sum += n % 10;
    		n /= 10;
    	}
    	return sum;
    }
    
    // 初始化:筛法计算质数;并计算这些质数的数字和
    void calcprime() {
    	// 筛法计算质数
    	for (int i = 2; i < N; ++i) {
    		if (isPrime[i] == 0) {
    			for (int j = i + i; j < N; j += i) {
    				isPrime[j] = 1;
    			}
    		}
    	}
    	
    	int count = 0; // 质数的计数
    	for (int i = 2; i < N; ++i) {
    		if (isPrime[i] == 0) {
    			primeNumbers[count] = i;
    			primeDigitSum[count] = sumDigits(i); // 预保存质数的数字和,减少Smith数判断时的计算量
    			++count;
    		}
    	}
    }
    
    // 判断一个数是否是质数
    bool isPrimeNumber(int n) {
    	if (n < 2) {
    		return false;
    	}
    	// 如果小于N,直接用筛法的结果就可以判断。
    	if (n < N) {
    		return isPrime[n] == 0;
    	}
    	// 如果大于等于N,则用简单判别法
    	int max = (int)sqrt(n) + 1;
    	for (int i = 0; i < P && primeNumbers[i] <= max; ++i) {
    		if (n % primeNumbers[i] == 0) {
    			return false;
    		}
    	}
    	return true;
    }
    
    // 判断一个数是否是Smith数,要在N范围内才有效。
    bool isSmithNumber(int n) {
    	if (isPrimeNumber(n)) {
    		return false;
    	}
    	
    	int nSum = sumDigits(n);	
    	int pSum = 0;
    	
    	// 分解因子,分解过程中直接计算数字和
    	int i;
    	for (i = 0; i < P && primeNumbers[i] <= n; ++i) {
    		// 这个循环里计算小于等于MAX_PRIME的因子
    		while (n % primeNumbers[i] == 0) {
    			n /= primeNumbers[i];
    			pSum += primeDigitSum[i];
    		}
    	}
    	// 若此时n>1,则表明n不是MAX_PRIME以内因子产生的合数,
    	// 又因为MAX_PRIME以内质数相乘得到的合数一定在10,000,000范围内,
    	// 所以n一定是质数,要计算这个因子的数字和
    	if (n > 1) {
    		pSum += sumDigits(n);
    	}
    	
    	return pSum == nSum;
    }
    
    int main() {
    	calcprime();
    
    	int n;
    	while (cin >> n, n > 0) {
    		while (!isSmithNumber(++n));
    		cout << n << endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark RDD(Resilient Distributed Datasets)论文
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    【机器学习实战】第10章 K-Means(K-均值)聚类算法
    [译]flexbox全揭秘
  • 原文地址:https://www.cnblogs.com/ajeyone/p/1840637.html
Copyright © 2020-2023  润新知