题目链接:HDU4768
测试一下,能否显示图片
题目大意:如果有学生拿了奇数张传单,输出其ID以及传单数量,否则输出DC Qiang is unhappy。
代码来自:队友@Vectorhr + 大佬的队伍@bhza8987510 (WHU-潘俊霖)
下面提供两种做法,代码里注释写的很清楚,直接看代码就好啦
AC代码1:
/*
2017年8月25日11:15:13
HDU4768
异或的性质
AC
*/
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
using namespace std;
const int maxn=2e5+5;
typedef long long ll;
ll a[maxn],b[maxn],c[maxn];
int main(){
ll n,res,sum;
while(~scanf("%lld",&n)){
res=sum=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for(ll i=1;i<=n;i++){
scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
}
for(ll i=1;i<=n;i++){
for(ll j=a[i];j<=b[i];j+=c[i]){
// printf("%lld^%lld= %lld\n",j,res,res^j);
/*
这里用到了异或的性质,同一个数异或偶数次结果为0,
异或奇数次为其本身,所以如果res为0,那么每个数都出现了偶数次,
否则res就等于出现了奇数次的那个人的标号。
很巧妙!记得开Long long 可能会爆
*/
res^=j;
}
}
if(res){
for(ll i=1;i<=n;i++){
/*统计每一组a,b,c对这个人的贡献,每一组最多贡献1*/
if(res>=a[i]&&res<=b[i]&&((res-a[i])%c[i])==0) ++sum;
}
//printf("res=%lld",res);
printf("%lld %lld\n",res,sum);
}
else{
printf("DC Qiang is unhappy.\n");
}
}
return 0;
}
AC代码2:
/*
2017年8月25日11:19:04
HDU4758
二分查找
AC
*/
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
using namespace std;
const int maxn=2e4+10;
typedef long long ll;
const ll inf=0x3f3f3f3f;
ll a[maxn],b[maxn],c[maxn];
ll tot;
int main(){
int n;
while(~scanf("%d",&n)){
tot=0;
ll mx=-inf,mi=inf;
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
mx=max(b[i],mx);
mi=min(a[i],mi);
tot+=(b[i]-a[i])/c[i]+1;//对每一组a,b,c贡献的传单数量求和
}
if((tot&1)==0) printf("DC Qiang is unhappy.\n");
else{
//利用二分,求出使得传单数量为奇数的那个人的标号
ll mid=(mx+mi)>>1;
ll r=mx;
ll l=mi;
while(l<r){
tot=0;
for(int i=1;i<=n;i++){
if(mid<a[i]) continue;
else{
tot+=(min(mid,b[i])-a[i])/c[i]+1;
}
}
if((tot&1)==0) l=mid+1;
else r=mid;
mid=(l+r)>>1;
}
ll ans=0;
for(int i=1;i<=n;i++){
/*统计每一组a,b,c对这个人的贡献,每一组最多贡献1*/
if(r>=a[i]&&r<=b[i]&&((r-a[i])%c[i]==0)) ans++;
}
printf("%lld %lld\n",r,ans);
}
}
return 0;
}