http://bailian.openjudge.cn/practice/3454?lang=en_US
题目
在秦腾进入北京大学学习的第一个学期,就不幸遇到了前所未有的教学评估。在教学评估期间,同学们被要求八点起床,十一点回宿舍睡觉,不准旷课,上课不准迟到,上课不准睡觉……甚至连著名的北大三角地也在教学评估期间被以影响校容的理由被拆除。这些“变态”规定令习惯了自由自在随性生活学习的北大同学叫苦不迭。
这一天又到了星期五,一大早就是秦腾最不喜欢的高等代数课。可是因为是教学评估时期,不能迟到,于是他在八点五分的时候挣扎着爬出了宿舍,希望能赶快混进在八点钟已经上课了的教室。可是,刚一出宿舍楼门他就傻眼了: 从宿舍到教学楼的路上已经站满了教学评估团的成员。他们的目的就是抓住像他这样迟到的学生,扣除学校的分数。
秦腾当然不能让评估团得逞。他经过观察发现,整个评估团分成了N个小组,每个小组的成员都分布在从宿舍楼到教学楼的路上的某一段,并且同一小组的成员间的距离是相等的。于是,我们可以用三个整数S, E, D来描述评估团的小组: 既该小组的成员在从宿舍到教学楼的路上的:
S, S + D, S + 2D, …, S + KD (K ∈ Z, S + KD ≤ E, S + (K + 1)D > E)位置。
观察到了教学评估团的这一特点,又经过了认真的思考,秦腾想出了对策: 如果在路上的某一位置有奇数个教学评估团成员,他就可以运用调虎离山,声东击西,隔山打牛,暗度陈仓……等方法,以这一地点为突破口到达教学楼。但是由于教学评估团的成员的十分狡猾,成员位置安排的设计极其精妙,导致在整条路上几乎没有这样的位置出现。即使由于安排不慎重出现了这样的位置,最多也仅有一个。现在秦腾观察出了所有小组的安排,但是由于整个教学评估团的人数太多,他实在看不出这样的位置是否存在。现在,你的任务是写一个程序,帮助他做出判断。
Input
输入文件的第一行为一个整数T,接下来输入T组相互独立的测试数据。
每组测试数据的第一行包含一个整数,代表N
接下来的N行,每行三个整数Si, Ei, Di, 代表第i个小组对应的三个参数。
Output
对于每个测试数据,如果题目中所求的位置不存在,既任意位置都有偶数个教学评估团的成员存在,在输出文件的中打印一行:
"Poor QIN Teng:(" (不包含引号)
否则打印两个整数Posi, Count,代表在唯一的位置Posi,有Count个教学评估团的成员。根据题意,Count应为奇数。
Sample Input
3 2 1 10 1 2 10 1 2 1 10 1 1 10 1 4 1 10 1 4 4 1 1 5 1 6 10 1
Sample Output
1 1 Poor QIN Teng:( 4 3
题解
因为最多只有一个位置出现奇数,所以前缀和只有两种情况
- 从某一项开始全为奇数
- 全为偶数
所以二分得到第一个为奇数的项就可以了
为了加速判断,可以直接判断最后一项是不是奇数,虽然渐进复杂度并没有改变。
AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#define REP(r,x,y) for(register int r=(x); r<(y); r++)
using namespace std;
template<class T>
inline void read(T &x) {
x=0; char ch; do ch=getchar(); while(!isdigit(ch));
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
}
#define MAXN 200007
struct node {
int s,e,d;
// bool operator<(const node &r) const {
// if(s!=r.s) return s<r.s;
// return e<r.e;
// }
} pos[MAXN];
int n;
inline bool in(int i, int x) {
return x>=pos[i].s && x<=pos[i].e;
}
inline bool vali(int x) {
int k=0;
REP(i,0,n) {
if(in(i,x)) {
k+=(x-pos[i].s)/pos[i].d+1;
} else if(x>=pos[i].s) {
k+=(pos[i].e-pos[i].s)/pos[i].d+1;
}
}
return k&1;
}
inline bool is(int i, int x) {
return in(i,x) && !((x-pos[i].s)%pos[i].d);
}
inline int calc(int x) {
int k=0;
REP(i,0,n) {
if(is(i,x)) {
k++;
}
}
return k;
}
int main() {
int t; read(t);
while(0<t--) {
read(n);
REP(i,0,n) {
read(pos[i].s); read(pos[i].e); read(pos[i].d);
}
// sort(pos,pos+n);
unsigned int l=0, r=(1u<<31);
while(l<r) {
int m=(l+r)>>1;
if(vali(m)) r=m;
else l=m+1;
}
if(l<(1u<<31)) printf("%d %d\n", l, calc(l));
else puts("Poor QIN Teng:(");
}
return 0;
}