math1142

题意:给定一个数n,若n的各位数之和与n的所有质因数各位之和相等,则n为simth数。现在对于输入的一个数n,找出一个大于n的最小的一个simth数,并输出。

譬如:4937775 = 3*5*5*65837,而3+5+5+6+5+8+3+7 = 42,4+9+3+7+7+7+5 = 42

首先有如下性质:

1 任意合数都可被分解为几个质因数的乘积

2 给定合数的质因数分解表达式唯一

根据上述性质,我们的质因数分解思路如下:

设被分解合数为N,则分解步骤如下:

初始状态,M = 2

用M试除N,若能整除,说明M为N的质因数,则更新N = N / M,M不变;若不能整除,则N不变,M++

上述方法蕴涵两个特性:

1 被当前M整除的N其所有质因数均大于等于M。譬如:N若能被5整除,则其所有质因数均大于等于5,即其不可能再被2或3整除(程序从小到大遍历,先用小的试除,再用大的试)

2 不需要判断当前M是否为素数,因为若为合数则必然不能整除。证明如下:假设M当前为合数,且M的一个质因数为P,则若N能被M整除则必然能被P整除,这与特性1矛盾

#include <stdio.h>

#include <math.h>

void get_sum(long n, int * sum)

{  //逐位求和

while(n != 0){

*sum += n%10;

n /= 10;

}

}

int main(){

int sum1, sum2;

long ceil, n, nn, m;

int cnt;

while(1){

scanf("%ld", &ceil);

if(ceil == 0) break;

for(nn = ceil+1; ; nn++){

sum1 = sum2 = cnt = 0;

get_sum(nn, &sum1);

n = nn;  //nn固定保存原N值,n用于整除后更新N值

m = 2;

while(m <= sqrt(n))//因数范围在2-sqrt(n),且这里的N是逐渐减小的

{

if(n%m == 0)//如果m可以被使用,则可能下一个因数还是M,因此m不能自加1

{

cnt++;  //cnt记录质因数个数,即标识了是否为素数

n = n/m;//N是逐渐减小的,因为n的因数始终小于根号n

get_sum(m, &sum2);

}

else m++;

}

get_sum(n, &sum2);//最后剩余的N是最后一个质数,还要加上去

if(sum1 == sum2 && cnt != 0){

printf("%ld\n", nn);

break;

}

}

}

return 0;

}

时间: 2024-12-29 06:52:10

math1142的相关文章