题目不难,素数判定+整数唯一分解定理
大致题意为:定义smith数如下:正整数n,满足:令ans=∑ni,ni为n的各个位数字。n=prime1*prime2*prime3……*primen,其中prime i 为素数。令Sum=∑∑primei,其中∑primei表示对于primei素数,其各个位上的数字之和。若Sum=ans且n不为素数,则可以认为n为smith数,现在题目给定一个正整数,要求出比该数大的最小smith数。
题意很明确。主要涉及到素数的判定和整数唯一分解定理。
1)素数判定,这个直接用传统的方法就可以了。时间复杂度为O(log√n)
2)整数唯一分解定理:对于任意的正整数(n>1)都可以唯一的分解成如下的形式:
N=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 其中pi均为素数,ki大于0
那么本题要求的实际上就是Sum=∑ki∑primei是否为ans=∑ni。
知道了上面两点,思路应该说很明晰了:枚举比n大的数字,依次判定是否为素数,若不为素数再判定是否满足Sum==ans,若满足则为最小smith数,否则不是,继续枚举。
下面是代码:168K+16MS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int n,ans;
bool Is_prime(int x){ //判定是否为素数
for(int i=2;i<=int(sqrt(double(x)));i++)
if(x%i==0)
return false;
return true;
}
bool Is_smith(int x){ //判定是否为smith数
int Sum=0;
int i=2;
while(i*i<=x){ //筛法求整数分解素数各项(值和幂)
if(x%i==0){ //若可以整除
int s=0,temp=i;
while(temp>0){ //求该素数个位累计之和
s+=temp%10;
temp/=10;
}
int j=0; //求该素数因子的幂
while(x%i==0){
j++;
x/=i;
}
Sum+=s*j; //累加 j 个 s
}
if(i==2) //若为2,则下一个奇数为3
i++;
else //否则为奇数,下一个奇数为i+2
i+=2;
}
if(x!=1){ //若还没有整除完毕,则x为素数因子,其幂为1
while(x>0){ // 累加x的各位之和
Sum+=x%10;
x/=10;
}
}
if(Sum==ans) //判断是否相等
return true;
return false; //不相等
}
int main(){
while(scanf("%d",&n),n){
n++; //从n+1开始枚举
while(true){
if(!Is_prime(n)){ //先判断是否为素数
ans=0;
int temp=n;
while(temp>0){ //累加求n的各位之和
ans+=temp%10;
temp/=10;
}
if(Is_smith(n)){ // 若为smith数,则输出最小数,退出
printf("%d\n",n);
break;
}
}
n++; //否则继续枚举
}
}
return 0;
}