题意
秦腾与教学评估在秦腾进入北京大学学习的第一个学期,就不幸遇到了前所未有的教学评估。在教学评估期间,同学们被要求八点起床,十一点回宿舍睡觉,不准旷课,上课不准迟到,上课不准睡觉……甚至连著名的北大三角地也在教学评估期间被以影响校容的理由被拆除。这些“变态”规定令习惯了自由自在随性生活学习的北大同学叫苦不迭。 这一天又到了星期五,一大早就是秦腾最不喜欢的高等代数课。可是因为是教学评估时期,不能迟到,于是他在八点五分的时候挣扎着爬出了宿舍,希望能赶快混进在八点钟已经上课了的教室。可是,刚一出宿舍楼门他就傻眼了: 从宿舍到教学楼的路上已经站满了教学评估团的成员。他们的目的就是抓住像他这样迟到的学生,扣除学校的分数。 秦腾当然不能让评估团得逞。他经过观察发现,整个评估团分成了N个小组,每个小组的成员都分布在从宿舍楼到教学楼的路上的某一段,并且同一小组的成员间的距离是相等的。于是,我们可以用三个整数S, E, D来描述评估团的小组: 既该小组的成员在从宿舍到教学楼的路上的: S, S + D, S + 2D, …, S + KD (K ∈ Z, S + KD ≤ E, S + (K + 1)D > E)位置。 观察到了教学评估团的这一特点,又经过了认真的思考,秦腾想出了对策: 如果在路上的某一位置有奇数个教学评估团成员,他就可以运用调虎离山,声东击西,隔山打牛,暗度陈仓……等方法,以这一地点为突破口到达教学楼。但是由于教学评估团的成员的十分狡猾,成员位置安排的设计极其精妙,导致在整条路上几乎没有这样的位置出现。即使由于安排不慎重出现了这样的位置,最多也仅有一个。现在秦腾观察出了所有小组的安排,但是由于整个教学评估团的人数太多,他实在看不出这样的位置是否存在。现在,你的任务是写一个程序,帮助他做出判断。
(100%的数据满足教学评估团的总人数不大于10^8 是错的!)
思路
因为只有一个点是奇数,所以计算某点之前的所有人。二分某点,若人数为偶,向后。为奇,向前。
(法二-将所有位置数xor起来,然后仅剩的结果就是第一问答案,但时间复杂度超了)
代码
#include <iostream>
using namespace std;
#define NMAX 200001
const long long int INF= (~0u>>1) +1;
long long int S[NMAX],E[NMAX],D[NMAX];
long long l,r,m;
long long int n;
long long countN(long long t)
{
long long ret=0;
for (int i=0;i<n;i++)
{
if (S[i]>t)continue;
if (t<E[i])
ret+=(t-S[i])/D[i]+1;
else
ret+=(E[i]-S[i])/D[i]+1;
}
return ret;
}
void solve()
{
scanf("%d",&n);
for (int i=0;i<n;i++)
scanf("%lld%lld%lld",S+i,E+i,D+i);
l=0;r=INF;
while (l<r-1)
{
m=(l+r)>>1;
if (countN(m)%2==0) l=m;
else r=m;
}
if (r==INF) printf("Poor QIN Teng:(\n");
else printf("%lld %lld\n",r,countN(r)-countN(r-1));
}
int main()
{
int TT;
scanf("%d",&TT);
while(TT--)
solve();
return 0;
}
来源 http://www.lydsy.com/JudgeOnline/problem.php?id=1271