zoukankan      html  css  js  c++  java
  • hdu4768 非常规的二分

    题意:
          n个社团给同学发传单,同学一共有1--2^31这么多,每个社团有三个数A ,B ,C ,只有
    满足 A ,A + C ,A + C + C ...A + KC <= B 的学生才能得到传单,问你谁收到的传单数是奇数,题目保证给的测试数据要么没有奇数的,要么只有一个是奇数个传单.

    思路:

         "题目保证给的测试数据要么没有奇数的,要么只有一个是奇数个传单." ,这句非常关键,我们二分枚举1--2^31,对于mid,算出0--mid一共发出去tmp张传单,如果tmp是偶数那么奇数的那个人一定不会在前面,因为只有一个奇数,其他的都是偶数,奇数 + 偶数 = 奇数,偶数+ 偶数 = 偶数,所以可以根据当前的数是不是偶数就能断定奇数的那个人在不在mid前面.对于不存在的这个判定,我是前直接跑出所有的个数,也就是求出范围INF以前的所有,如果偶数那么就不存在,否则就二分找,找到后在枚举这个找到的人有多少个传单,输出来就行了.这个只是用二分的特性去节省时间,和以往的二分不同,因为他不是在单调函数上查找的.所以这个我感觉是一个非常规的二分.


    #include<stdio.h>
    
    #define N 20000 + 100
    
    typedef struct
    {
       __int64 A ,B ,C;
    }NODE;
    
    NODE node[N];
    
    
    __int64 minn(__int64 x ,__int64 y)
    {
       return x < y ? x : y;
    }
    
    __int64 solve(__int64 mid ,int n)
    {
       __int64 sum = 0;
       for(int i = 1 ;i <= n ;i ++)
       {
          if(mid >= node[i].A)
          {
             sum += ((minn(mid ,node[i].B) - node[i].A) / node[i].C + 1);
          }
       }
       return sum;
    }
          
    
    int main ()
    {
       int n ,i;
       __int64 INF = 1;
       for(__int64 ii = 1 ;ii <= 31 ;ii ++)
       INF *= 2;
       while(~scanf("%d" ,&n))
       {
          for(i = 1 ;i <= n ;i ++)
          scanf("%I64d %I64d %I64d" ,&node[i].A ,&node[i].B ,&node[i].C);  
          __int64 tmp = solve(INF ,n);
          if(tmp % 2 == 0)
          {
             puts("DC Qiang is unhappy.");
             continue;
          }  
          __int64 low ,up ,mid;
          low = 0 ,up = INF;
          __int64 ans_id = -1;
          while(low <= up)
          {
             mid = (low + up) / 2;
             tmp = solve(mid ,n);
             //printf("%I64d******
    " ,tmp);
             if(tmp % 2)
             {
                up = mid -  1;
                ans_id = mid;
             }
             else 
             {
               low = mid + 1;
             }
          }
          __int64 ans_sum = 0;
          for(i = 1 ;i <= n ;i ++)
          {
             if(ans_id <= node[i].B && (ans_id - node[i].A) % node[i].C == 0 && ans_id >= node[i].A)
             ans_sum ++;
          }
          printf("%I64d %I64d
    " ,ans_id ,ans_sum);
       }
       return 0;
    }
    



  • 相关阅读:
    JS倒计时执行操作
    美化radio和checkbox样式
    ajax 多个表单值问题,表单序列化加其它表单值
    .net中的路径问题
    Response.Redirect 打开新窗口的两种方法
    GRIDVIEW FINDCONTROL的使用
    如何验证gridview控件的编辑行?如何获得gridview模板列<ItemTemplate/>中Label值?
    在Repeater的HeaderTemplate和FooterTemplate模板中寻找控件FindControl
    在GridView中使用FindControl(2)
    构造函数(C# 编程指南)
  • 原文地址:https://www.cnblogs.com/csnd/p/12063127.html
Copyright © 2011-2022 走看看