HDU:4379 The More The Better

这个题目也算折磨了我一下午了。

解决问题关键在于Yi + Yj <= L  。这说明序列Y中至多有1个数字可以大于等于L/2,否则两者之和将大于L。而序列X中任意小于等于L/2都可以放进序列Y中,而大于等于L/2的至多有一个。
如果有的话,那么一定是X中大于等于L/2那些序列里面最小的那一个。只要这个最小的与Y序列(即X中小于等于L/2的序列)最大的那个之和小于等于L,就能够把这个最小的放进Y中。

 
这里有个地方要注意,当 mod<=L/2 ,所得X必定都是小于L/2的,所以直接输出n就可以了。否则将会超时。

 

我一开始想按常规思路开个数组把序列存起来,但是2*107 如此之大的数据量存下并不方便。而且循环嵌套容易超时。于是我想到了序列X的周期性。。。但是依旧很麻烦。最后还是放弃了问了别人。

但是还是一直都错。

第一个问题是关于MAX,MIN的初始值的处理上,开始的时候我定义它们为int,分别取值MAX=-2147483648,MIN=2147483647,这是int的上下界。但是问题也因此出现,当MIN没有被覆盖(当然MAX被覆盖了),运行到mn+mx<=L这句就会发生溢出的问题,悲剧。

开始数据类型全用int,用一组极大的数据【20000000 2000000000 1000000000 1000000000 1999999999】,我依次输出所得每个x,发现全部溢出,于是改用long long。但是A,B,mod等还是int,得到结果还是溢出,我数据类型转换方面学的并不精通,所以干脆所有数据都换成long long 。奇怪的是将A,B等定义在main中会出现错误结果,改为全局变量于是AC。

 

查了一下。

 

使用全局变量程序运行时速度更快一些(因为内存不需要再分配),不过在计算机配置很高的今天,也快不了多少。

 

学的还是不到家,有人scanf输入用%I64d即使存局部变量也不会出现我有的问题。

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
long long  n,L,A,B,mod;
int main()
{

    //freopen("in.txt","r",stdin);
    while(scanf("%lld %lld %lld %lld %lld",&n,&L,&A,&B,&mod)!=EOF)
    {
        if(mod<=L/2)
        {
            printf("%d\n",n);
            continue;
        }
       int count=0;
       long long  mn=L+1,mx=-1;
       for(int i=1;i<=n;++i)
       {
           long long res=((A*i)+B)%mod;
           if(res<=L/2)
           {
             count++;
           if(res>mx) mx=res;
           }
           else
           {
           if(res<mn) mn=res;
           }
       }
       if(mn<=L&&mn+mx<=L)count++;
       printf("%d\n",count);
    }
    return 0;
}



 研究了一下数据类型转换,如果是 long long = int *int ,int*int将得到int类型再转为longlong,可能有精度损失,可以使用强制转换,将两个int都强转为longlong再相乘。

你可能感兴趣的:(HDU:4379 The More The Better)