ZOJ 1133 Smith Numbers

来源:互联网 发布:java程序员买书 编辑:程序博客网 时间:2024/05/21 22:33

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;}


0 0