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 }
越努力,越幸运