POJ-3484 Showstopper---二分+前缀和

题目链接:

https://cn.vjudge.net/problem/POJ-3484

题目大意:

给出一系列等差数列,给出第一项和最后一项和公差

这些等差数列中每个数出现的次数只有一个是奇数,找出这个数,并求出其出现的次数

解题思路:

二分枚举这个数,但是只是二分这个数字的话,找不到二分的条件。

所以枚举判断的时候,求出小于等于这个数字的数有多少个,如果是奇数个,说明该数 >= 解

如果是偶数,该数 < 解

输入很坑,数据与数据之间可能有多个空行

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn = 1e7 + 10;
 8 const double eps = 1e-5;
 9 struct node
10 {
11     ll l, r, d;
12 }a[maxn];
13 int n;
14 bool read()
15 {
16     bool ok = 0;
17     n = 0;
18     char s[100];
19     while(gets(s))
20     {
21         if(strlen(s) == 0)
22         {
23             if(ok)break;
24             continue;
25         }
26         ok = 1;
27         sscanf(s, "%lld%lld%lld", &a[n].l, &a[n].r, &a[n].d);
28         n++;
29     }
30     return ok;
31 }
32 ll judge(ll mid)
33 {
34     ll tot = 0;
35     for(int i = 0; i < n; i++)
36     {
37         if(mid < a[i].l)continue;
38         if(mid > a[i].r)
39             tot += (a[i].r - a[i].l) / a[i].d + 1;//注意加一,两种情况都需要加一
40         else
41         {
42             tot += (mid - a[i].l) / a[i].d + 1;
43         }
44     }
45     return tot;
46 }
47 int main()
48 {
49     while(read())
50     {
51         ll l = 1, r = 1LL << 33, ans = 0;
52         while(l <= r)
53         {
54             ll mid = (l + r) / 2;
55             //cout<<mid<<" "<<judge(mid)<<endl;
56             if(judge(mid) & 1)
57             {
58                 ans = mid;
59                 r = mid - 1;
60             }
61             else l = mid + 1;
62         }
63         if(ans == 0)
64         {
65             printf("no corruption\n");
66             continue;
67         }
68         ll tot = 0;
69         for(int i = 0; i < n; i++)
70         {
71             if(ans >= a[i].l && ans <= a[i].r && ((ans - a[i].l) % a[i].d == 0))tot++;
72         }
73         printf("%lld %lld\n", ans, tot);
74     }
75     return 0;
76 }

 

posted @ 2018-05-12 23:33  _努力努力再努力x  阅读(270)  评论(0编辑  收藏  举报