hdu 2608 0 or 1

3 篇文章 0 订阅
0 篇文章 0 订阅

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2608 

题目大意是定义一个T(n)为n所有正因子之和。然后定义S(n)为T(1)+T(2)……T(n)之和,求S(n)对2取余。

显然这是一个数论题,数据范围是32位整数,范围很多大,可以猜测,应该存在某种规律。

一定要敢于尝试,而且不要手懒,我们可以很快的暴力打一个100范围的T(n)表,然后看看,能不能找出规律。这里一定不要着急,有时候直接打S(n)的表可能看不出结果,所以一定要慢慢来。

暴力打表代码如下:

#include <stdio.h>

#define M 100

int a[M];
int main()
{
    int i,j;
    for(i=1;i<M;i++)
    {
        for(j=i;j<M;j+=i)
        {
            a[j]+=i;
        }
    }
    for(i=0;i<M;i++)
    {
        printf("%3d: %3d\n",i,a[i]&1);
    }
    return 0;
}
看到结果,我们发现大部分数据都是0,只有少部分是1,分别是1、2、4、8、9、16、18、25、32、36……细心点会发现T[i*i]会是,T[2*i*i]也是1,当你看出这一点时,这题可做了。

题目给出N,只需求出[1,N]有多少个这样的数记为Cnt,然后把Cnt%2就可以了。像这样:

for(Cnt=0,i=1;i<N;i++)
{
    if(i*i<=N)
    {
        Cnt++;
    }
    if(2*i*i<=N)
    {
        Cnt++;
    }
}
printf("%d\n",Cnt&1);
这需要考虑如果2*i*i能写成a*a,这样就多计数了一次,但是显然可以证明,不存在那样的数。

如果在舍得动一下脑筋就可以写成:

#include <stdio.h>
#include <math.h>

int main()
{
    int T,s,N,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        k=sqrt(N);
        s=k;
        while(k*k*2>N)
        {
            k--;
        }
        s+=k;
        printf("%d\n",s&1);
    }
    return 0;
}
如果再肯多想一点,sqrt(N/2.0)就是2*i*i的上限所以就可以这样写:
#include <stdio.h>
#include <math.h>

int main()
{
    int T,N;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        printf("%d\n",((int)sqrt(N)+(int)sqrt(N/2.0))&1);
    }
    return 0;
}

其实sqrt(N/2)也是对的。显然偶数肯定对,其实奇数时也对的,因为可以证明sqrt(a)与sqrt(a+0.5)在取整之后一定一样,sqrt(a)可能为整数,但sqrt(a+0.5)是不可能为整数的,所以里面加上0.5也是不能使整数部分加一的。但是懒得想这么多,保险起见,还是尽量别丢精度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值