首页 > 其他分享 >Smith Number

Smith Number

时间:2023-12-10 19:33:07浏览次数:20  
标签:candidate self Smith number Number result primes 质数

题目

Given a number n, the task is to find out whether this number is a Smith number or not. A Smith number is a composite number whose sum of digits is equal to the sum of digits of its prime factors.

Example 1:

Input:
n = 4
Output:
1
Explanation:
The sum of the digits of 4 is 4, and the sum of the digits of its prime factors is 2 + 2 = 4.

Example 2:

Input:
n = 378
Output:
1
Explanation:
378 = 21*33*71 is a Smith number since 3+7+8 = 2*1+3*3+7*1.

Your Task:
You don't need to read input or print anything. Your task is to complete the function smithNum() which takes an Integer n as input and returns the answer.

Expected Time Complexity: O(n * log(n))
Expected Auxiliary Space: O(n)

Constraints:
\(1 \le n \le 10^5\)

解题过程

class Solution:
    primes = [2, 3, 5, 7]

    def primeFactors(self, n):
        assert n >= 2
        result = {}
        for i in self.primes:
            while n % i == 0:
                n = n // i
                result[i] = result.get(i, 0) + 1
                if n == 1:
                    return result

        # update primes, only function when `n > self.primes[-1]`
        candidate = self.primes[-1] + 2
        while True:
            if all(candidate % i != 0 for i in self.primes):  # not prime
                self.primes.append(candidate)
                while n % candidate == 0:
                    n = n // candidate
                    result[candidate] = result.get(candidate, 0) + 1
                    if n == 1:
                        return result
            candidate += 2

    def smithNum(self, n):
        if n <= 1:
            return 0
        prime_factors = self.primeFactors(n)
        if n in self.primes:
            return 0  # it is a prime, so not smithNum

        sum_digits = lambda k: sum(int(i) for i in str(k))
        v1 = sum_digits(n)
        v2 = sum(v * sum_digits(k) for k, v in prime_factors.items())
        return int(v1 == v2)

我刚开始使用的方法是,用一个列表进行缓存,需要判断的数字比缓存的最大质数还大时,就找下一个质数(通过加2的形式)。
这个思路来自于一个“找第N个质数”的题目。
但是这个超时了,数字特别大时,这个会很耗时,因为每次加2只保证了不会装上2的倍数,对新的数字需要与所有已知的质数进行整除判断

然后我就想到,有一个可以找到0-N内所有质数的算法。
但是这道题目里,没有指定范围,每次范围超出已知质数时,从0开始找也不太好。
于是我就改成了,如果数字大于缓存列表最大质数时,找到最大质数到这个数字之间的所有质数。相当于两个方法结合在一起,尽可能用到质数时再计算。

import numpy as np


class Solution:
    def __init__(self):
        # initial primes
        self.primes = [2, 3, 5, 7]
        self.last_num = self.primes[-1]

    def primeFactors(self, n):
        result = {}
        if n <= 1:
            return result

        # try to simplify n with known primes
        for i in self.primes:
            while n % i == 0:
                n = n // i
                result[i] = result.get(i, 0) + 1
                if n == 1:
                    return result

        # update primes ranging from start to n
        start = self.last_num + 1
        candidates = np.ones(n + 1)  # 0 to n
        for p in self.primes:
            k = int(np.ceil(start / p) * p)
            while k < candidates.size:
                candidates[k] = 0
                k += p
        new_primes = []
        for idx, v in enumerate(candidates[start:]):
            if v:
                p = idx + start
                new_primes.append(p)
                k = 2 * p
                while k < candidates.size:
                    candidates[k] = 0
                    k += p
        self.primes.extend(new_primes)
        self.last_num = n

        # using new primes to simplify n
        for i in new_primes:
            while n % i == 0:
                n = n // i
                result[i] = result.get(i, 0) + 1
                if n == 1:
                    return result

    def smithNum(self, n):
        if n <= 1:
            return 0
        prime_factors = self.primeFactors(n)
        if n in self.primes:
            return 0  # it is a prime, so not smithNum

        sum_digits = lambda k: sum(int(i) for i in str(k))
        v1 = sum_digits(n)
        v2 = sum(v * sum_digits(k) for k, v in prime_factors.items())
        return int(v1 == v2)

答案

看了看答案,思路是是先算出来一定范围内的所有质数,然后用这个表去计算。
和我的第二个思路比较像,不过我的第二个思路里,只有在需要时才计算新的质数,这个刚开始就找到所有质数。感觉见仁见智吧。

下面是根据答案改出来的可以提交的代码(默默吐槽一下,根本不是 Python 的代码风格……)。
不过,这个最后也超时了!我不知道是系统的原因还是Python语言的原因……

import math

MAX  = 10000
primes = []

# utility function for sieve of sundaram
def sieveSundaram():
    #In general Sieve of Sundaram, produces primes smaller
    # than (2*x + 2) for a number given number x. Since
    # we want primes smaller than MAX, we reduce MAX to half
    # This array is used to separate numbers of the form
    # i+j+2ij from others where 1 <= i <= j
    marked  = [0] * int((MAX/2)+100)
    # Main logic of Sundaram. Mark all numbers which
    # do not generate prime number by doing 2*i+1
    i = 1
    while i <= ((math.sqrt (MAX)-1)/2) :
        j = (i* (i+1)) << 1
        while j <= MAX/2 :
            marked[j] = 1
            j = j+ 2 * i + 1
        i = i + 1
    # Since 2 is a prime number
    primes.append (2)
    
    # Print other primes. Remaining primes are of the
    # form 2*i + 1 such that marked[i] is false.
    i=1
    while i <= MAX /2 :
        if marked[i] == 0 :
            primes.append( 2* i + 1)
        i=i+1


class Solution:

    def __init__(self):
        sieveSundaram()
        
    def smithNum(self, n):
        original_no = n
        
        #Find sum the digits of prime factors of n
        pDigitSum = 0;
        i=0
        while (primes[i] <= n/2 ) :
            
            while n % primes[i] == 0 :
                #If primes[i] is a prime factor ,
                # add its digits to pDigitSum.
                p = primes[i]
                n = n/p
                while p > 0 :
                    pDigitSum += (p % 10)
                    p = p/10
            i=i+1
        # If n!=1 then one prime factor still to be
        # summed up
        if not n == 1 and not n == original_no :
            while n > 0 :
                pDigitSum = pDigitSum + n%10
                n=n/10
          
        # All prime factors digits summed up
        # Now sum the original number digits
        sumDigits = 0
        while original_no > 0 :
            sumDigits = sumDigits + original_no % 10
            original_no = original_no/10
            
        #If sum of digits in prime factors and sum
        # of digits in original number are same, then
        # return true. Else return false.
        return int(pDigitSum == sumDigits)

更多参考资料

Smith Number -- from Wolfram MathWorld
质数(素数)计算器 - 判断一个数是否为质数/素数
素数筛法算法及其原理 - kentle - 博客园

标签:candidate,self,Smith,number,Number,result,primes,质数
From: https://www.cnblogs.com/zkmjolnir/p/17893088.html

相关文章

  • 转:ROW_NUMBER() OVER函数的基本用法
    ROW_NUMBER()OVER函数的基本用法 分组后排序    在oracle中分组倒叙排序,取出每一组的第一个值,如何通过ROW_NUMBER()OVER实现 ChatGPTChatGPT在Oracle中,你可以使用ROW_NUMBER()窗口函数结合PARTITIONBY和ORDERBY子句来实现......
  • CMC-ORACLE-函數row_number() over(partition by )函数用法
    row_number()over(partitionby)函数用法row_number()over(partitionby),作为oracle常用的分析函数,身为数据开发时必须要掌握的。不过一段时间不用,难免会有些忘记,今天整理一下一些场景下的用法。现有表(test_rownumber)有如下数据:RUSER(用户名)RID(用户编号)RSAL(用户消费)RD......
  • C - Sum of Numbers Greater Than Me
    C-SumofNumbersGreaterThanMehttps://atcoder.jp/contests/abc331/tasks/abc331_c 思路由于值可以是重复的,需要记录每出现的值对应的位置,记录在map<int,vector<int>>valpos;此处利用了mapkey的自动排序属性,把所有值进行从小到大做了排序,然后根据valpos......
  • CF55D Beautiful numbers
    题意给定序列\(S\)。求满足以下性质的\(S\)的排列的数量:\(\max_{j=1}^{i-1}s_j\ge2\timess_i\)或\(\max_{j=1}^{i-1}2\timess_j\les_i\)。Sol排个序先。设\(f_i\)表示我们从小到大往\(s\)里面填数,现在填的最大值为\(s_i\)的方案数。不难......
  • 无涯教程-Erlang - Numbers(数字)
    在Erlang中,有两种数字类型:整数(integers)和浮点数(floats)。整数示例:-module(helloLearnfk).-export([start/0]).start()->io:fwrite("~w",[1+1]).上面程序的输出如下:2浮点数示例:-module(helloLearnfk).-export([start/0]).start()->io:fwrite("~......
  • 数仓性能调优:row_number() over(p)-rn=1性能瓶颈发现和改写套路
    本文分享自华为云社区《GaussDB(DWS)性能调优:row_number()over(p)-rn=1性能瓶颈发现和改写套路》,作者:Zawami。1、改写场景本套路应用于子查询中含有row_number()over(partitionbyorderby)rn,并仅把rn列用于分类排序后筛选最大值的场景。2、性能分析GaussDB中SQL语句的执......
  • apache的数字工具类NumberUtils
    org.apache.commons.lang3.NumberUtils<!--StringUtils、NumberUtils等工具类--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.10</version></de......
  • 如何禁止type='number'的input框输入字母e
    很多时候input设置了type="number"还是能输入字母e,那么如何禁止呢?1.例如input框为<el-inputtype="number"v-model=""@keydown.native="keyInput"placeholder="请输入数字"></el-input>2.写方法//去除number输入框内ekeyInput(e){letkey=......
  • SP3889 Closest Number题解
    题意简述有两个\(n\)位十进制数\(a\),\(b\)。要将数字\(b\)的每一位重新排列后,使得得到的数字一个在大于等于\(a\)的情况下更接近\(a\),另一个在小于\(a\)的情况下更接近\(a\)。求这两个数,如果找不到就输出0。思路以大于等于\(a\)的为例。我们可以将\(b\)从小......
  • [Javascript] Using Generator to create a number generate with condition
    constgenerateTimeMs=(min,max)=>Math.floor(Math.random()*(max-min+1))+min/***Ageneratorwhichcangeneratenumbersbasedonsettings**@param{number}min-mintimervalue,unitms*@param{number}max-maxtimervalue,unit......