POJ - 3484 Showstopper 二分搜索

来源:互联网 发布:java图形程序设计 编辑:程序博客网 时间:2024/06/07 02:15

题目大意:给出N个X Y Z组合,其中X Y Z组合能够输出 X, X + Z, X + 2 * Z… X + K * Z(X+K * Z <= Y)问这些输出的数中,有哪个数是输出奇数次的

解题思路:输出保证最多只有一个奇数
假设J是输出奇数次的那个数,那么小于J的所有输出的数的个数之和就为偶数,大于等于J的所有输出的数的个数之和为奇数
如果以i为标准,输出小于等于i的所有数之和,i从小到大变化的话,就会有如下的形式
偶偶偶偶偶偶奇奇奇。。。第一个奇刚好是J
(具体的可以自己验证)
通过上面的规律,就可以通过二分搜索来求得J了

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define maxn 50010typedef long long ll;ll X[maxn], Y[maxn], Z[maxn];int cnt;char str[maxn];ll judge(ll mid) {    ll Sum = 0;    for(int i = 0; i < cnt; i++) {        if(mid < X[i])            continue;        ll t = min(mid, Y[i]);        Sum += (t - X[i])/ Z[i] + 1;    }    return Sum;}void solve() {    cnt = 1;    X[0] = 0;    sscanf(str,"%lld%lld%lld", &X[0], &Y[0], &Z[0]);    if(!X[0])        return ;    while(gets(str) && str[0]) {        sscanf(str,"%lld%lld%lld", &X[cnt], &Y[cnt], &Z[cnt]);        cnt++;    }    ll l = 0, r = 1LL << 32;    while(l < r) {        ll mid = (l + r) / 2;        if(judge(mid) % 2)            r = mid;        else            l = mid + 1;    }    if(l == (1LL << 32))        printf("no corruption\n");    else        printf("%lld %lld\n",l, judge(l) - judge(l - 1));}int main() {    while(gets(str))        solve();    return 0;}
0 2