hdu 4768 Flyer【二分】

来源:互联网 发布:mac系统开机密码忘了 编辑:程序博客网 时间:2024/04/28 08:40

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

题意:学校有N个社团,新学期开始之际这N个社团发传单,它们发

传单是有规律的,有三个数组A[maxn],B[maxn],C[maxn],第i个设

团值发给编号为x的同学,其中x=A[i]+k*C[i]且k为整数,x小于等于

B[i];学校学生标号1~2^31,求那个同学收到传单数为奇数和这位同学

收到的传单数目,题目保证最多有一位同学收到传单为奇数。

分析:题目保证的那句话很重要,由于学生的数目很大,所以不能考虑

枚举、暴力,联想到奇偶的传递性,在这道题中:偶+偶=偶,奇+偶=奇,

这样可以用二分来解决,mid=(l+r), sum=cal(mid)计算出1-mid

所有学生收到的传单总和,若sum为偶数则说明1-mid中不存在那位同学

否则存在,这样时间这个问题就迎刃而解了,做题真的需要思维联系,能够

充分利用所学知识,不然就白瞎了。

献上代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxh=20000+10;
const long long int inf=(1LL<<31);
long long int A[maxh],B[maxh],C[maxh];
long long int cal(long long int mid,int n)
{
    long long int top,sum=0;
    for(int i=0;i<n;i++)
    {
        top=min(mid,B[i]);
        if(top>=A[i])
        sum+=(top-A[i])/C[i]+1;
    }
    return sum;
}
int main()
{   
    int n;
    long long int l,r,mid;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        scanf("%I64d%I64d%I64d",&A[i],&B[i],&C[i]);
        l=0,r=inf;
        while(l<r)
        {
            mid=(l+r)/2;
            if(cal(mid,n)%2)r=mid;
            else l=mid+1;
        }
        if(l==inf)
        printf("DC Qiang is unhappy.\n");
        else
        printf("%I64d %I64d\n",l,cal(l,n)-cal(l-1,n));
    }
    return 0;
}
        
        
        
    
    

0 0
原创粉丝点击