Smith数的定义是各位数字之和与它的各个质因数(可以重复)的各位数字之和的总和相同的数,且不是素数。
题目本身是一道水题,数据尤其水。
下面的代码中加了一个优化:
先将所有询问按询问的数字升序排序,处理某个询问A时,如果结果是B,那么对其后询问值小于B的所有询问,都直接
给出答案为B。
例如:
23
24
25
26
27
0
在处理23时得到58,由于后面四个数都小于58,于是后面四个询问直接得到答案58而不必重复劳动。
最后再将所有询问按原先次序排序即可。
这样总体的平均时间复杂度介于O(m)和O(mlogm)之间,m为询问个数。
以下为代码。
时间:10毫秒
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
int prime[1200];
int Smith[5];
struct query{
int ask,pos,ans;
};
int cmp_by_ask(const void *a,const void *b){
return (*(query *)a).ask-(*(query *)b).ask;
}
int cmp_by_pos(const void *a,const void *b){
return (*(query *)a).pos-(*(query *)b).pos;
}
void getPrime(){
memset(prime,0,sizeof(prime));
int i,j,sq,flag;
prime[1]=2;
prime[2]=3;
prime[3]=5;
prime[4]=7;
prime[0]=4;
for(i=11;i<=10100;i++){
if(!(i%2&&i%3&&i%5&&i%7))continue;
sq=(int)(ceil(sqrt((double)i))+1);
flag=1;
for(j=11;j<=sq;j++){
if(i%j==0){
flag=0;
break;
}
}
if(flag){
prime[0]++;
prime[prime[0]]=i;
}
}
}
int getSum(int x){
int sum=0;
while(x){
sum+=(x%10);
x/=10;
}
return sum;
}
int is_Smith(int x){
int sum1=0,sum2=getSum(x),i,j,cnt=0;
for(i=1;i<=prime[0];i++){
while(x%prime[i]==0){
sum1+=getSum(prime[i]);
cnt++;
x/=prime[i];
}
}
if(x!=1){
sum1+=getSum(x);
cnt++;
}
if((sum1==sum2)&&(cnt>1))return 1;
else return 0;
}
int main(){
query p[50000];
int i,j,n,k,top;
top=0;
while(1){
scanf("%d",&p[top].ask);
if(p[top].ask==0)break;
p[top].pos=top;
p[top].ans=-1;
top++;
}
qsort(p,top,sizeof(p[0]),cmp_by_ask);
getPrime();
//for(i=0;i<top;i++){
//printf("%d ",p[i].ask);
//}//
//printf("\n");
for(i=0;i<top;i++){
//printf("I=%d.\n",i);
j=p[i].ask+1;
while(1){
if(is_Smith(j)){
p[i].ans=j;
break;
}
else j++;
}
//printf("j=%d.\n",j);
for(k=i+1;k<top;k++){
//printf("k=%d.\n",k);
if(p[k].ask<j){
p[k].ans=j;
}
else break;
}
//printf("***k=%d.\n",k);
i=k-1;
}
qsort(p,top,sizeof(p[0]),cmp_by_pos);
for(i=0;i<top;i++){
printf("%d\n",p[i].ans);
}
return 0;
}