Chinaunix首页 | 论坛 | 博客
  • 博客访问: 616663
  • 博文数量: 127
  • 博客积分: 6136
  • 博客等级: 准将
  • 技术积分: 1461
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 00:32

分类:

2010-06-24 16:58:32

《编程之美》的2.20题目,给出一段C#代码,要求不用电脑,理解程序并回答问题。下面是从C#代码中改写成的C代码:

#include <stdio.h>
#include <limits.h>

#define MAX64 9223372036854775807LL

int main()
{
    int rg[32];
    long long i;
    int hit=0;
    int hit1=-1;
    int hit2=-1;
    int j;
    for(i=2; i<32; i++)
        rg[i-2] = i;
    for(i=1; i < MAX64; i++)
    {
        hit=0;
        hit1=-1;
        hit2=-1;
        for(j=0; (j<30) && (hit<=2); j++)
        {
            if( (i%rg[j]) != 0 )
            {
                hit++;
                if(hit == 1)
                    hit1=j;
                else if(hit ==2)
                    hit2=j;
                else
                    break;
            }
        }
        if( (hit == 2) && ((hit1+1) == hit2))
            printf("found%lld\n", i);
    }
    return 1;
}

理解这个程序就是从输出的地方入手即可。这个程序输出的条件是hit==2&&(hit1+1==hit2),而hit表示满足i%r[j]!=0的条件的次数,hit==2表示这个条件只能被满足两次,也就是说对于一个i,在rg数组的30个数中,这个i能被其它28个数整除,而不能被其中两个数整除。而hit1表示第一个不能整除i的数的下标,hit2表示第二个不能整除i的下标,这两个下标被要求相差只有1。所以,程序所要寻找的是这样的数:这个数i不能被2-31这30个数中的两个相邻的数整除,但能被其它 28个数整除。
这里我们需要找到这两个相邻的数。设这两个数分别为A,A+1,如果i不能被A整除,那么,i必然不能被A的倍数整除。所以A必然大于15(因为给定的数的范围是2-31),即i必然能够被2-15之间的数整除,而18=2*9,20=4*5,22=2*11,。。。30=2*15。因为i必然能够被2-15之间的数整除,所以i,必然能够被18,20,。。。30这些数整除。那么最后只剩下16和17。所以,所求的i肯定不能被16和17整除,同时能够被其他28个数整除。那么i就是其它28个数的最小公倍数的整数倍。
用计算器计算出这个数是:2123581660200
阅读(1157) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~