HDU 1999 不可摸数

地址:http://acm.hdu.edu.cn/showproblem.php?pid=1999

思路1:

标准的筛选法。求出每个数的因子和,
然后看因子和是否在1000以内,是的话就证明等于因子和的这个数不是不可摸数。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h> 
 4 int sum[1000001],sign[1001];  //sum是因子数和,开的空间大些
 5 int main()
 6 {
 7     int n,num,i,j;
 8     scanf("%d",&n);
 9     for(i=1;i<=500000;++i)
10       for(j=2*i;j<=1000000;j+=i)
11          sum[j]+=i;    //这个过程是用筛选法求出每个数的因子和 
12     for(i=1;i<=1000000;++i)
13       if(sum[i]<1000)
14          sign[sum[i]]=1;   //说明在1000里存在一个数等于,则不是不可模数
15     while(n--)
16     {
17         scanf("%d",&num);
18         if(sign[num])
19          puts("no");
20         else
21          puts("yes");
22     }
23     return 0;
24 } 

 

 

思路2:

设输入n,因为1是所有数的约数,首先t=n-1;
如果此时 t 为素数,则n一定能被找到,eg:t*t,由于t是素数,t*t 的约数有且只有1和t,所以成立。
否则,如果 t 能表示为两个互不相等的素数的和,则n一定找到。
eg:i 为素数且t-i 也为素数,则 i*(t-i) 的约数一定只有 1,i ,t-i; 所以成立。
但是,if(i==(t-i)),则不一定,因为相同素数只取一次。
证毕。

 1 #include<stdio.h>
 2  int main()
 3  {
 4      int i,j,n,prime[1000]={1,1};
 5      for(i=2;i<1000;++i)
 6          if(!prime[i])
 7              for(j=i+i;j<1000;j+=i)
 8                  prime[j]=1;
 9      scanf("%d",&j);
10      while(j--){
11          scanf("%d",&n);
12          if(!prime[--n]){
13              puts("no");
14              continue;
15          }
16          for(i=2;i<=(n>>1);++i)
17              if(!prime[i]&&!prime[n-i])
18                  break;
19          if(i<=(n>>1)&&n!=(i<<1)) puts("no");
20          else puts("yes");
21      }
22      return 0;
23  }

 

 

posted on 2012-08-14 09:53  mycapple  阅读(547)  评论(0编辑  收藏  举报

导航