首页 > 代码库 > math1142
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;
}
math1142