HDU-4768 Flyer
题意:社团给1-
2
32
2^{32}
232编号的学生分发标签为i的宣传单,宣传单有n种,分发给编号是Ai,Ai+Ci,Ai+2Ci,…编号不超过Bi的学生,找出被发到传单为奇数的学生,保证最多只有一个。
题解:第一次见到二分是这种姿势的!因为只有包含有奇数的那个区间的区间和才会是奇数,简直妙极了…利用这个性质就可以二分区间了。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define IOS ios::sync_with_stdio(0),cin.tie(0)
#define sf(a) scanf("%d",&a)
#define dg(a) cout<<"#a"<<" "<<a<<endl
#define pi acos(double(-1))
using namespace std;
typedef long long ll;
const int N=2e4+10;
ll num[N][3];
int n,F;
typedef long long ll;
void findans(ll x)
{
ll cnt=0;
for(int i=1;i<=n;i++)
{
if(x>=num[i][0]&&x<=num[i][1]){
if((x-num[i][0])%num[i][2]==0){
cnt++;
}
}
}
if(cnt&1)cout<<x<<" "<<cnt<<endl;
else cout<<"DC Qiang is unhappy."<<endl;
}
bool check(ll l,ll r)
{
ll cnt=0;
ll tp1=l,tp2=r;
for(int i=1;i<=n;i++)
{
l=tp1,r=tp2;
l=max(l,num[i][0]),r=min(r,num[i][1]);
if(l>r)continue;
l-=num[i][0],r-=num[i][0];
ll res=r/num[i][2]+1;
if(l!=0)
{
res-=(l-1)/num[i][2]+1;
}
cnt+=res;
}
if(cnt&1)return true;
return false;
}
void solve()
{
for(int i=1;i<=n;i++)
{
cin>>num[i][0]>>num[i][1]>>num[i][2];
}
ll l=1,r=ll(1)<<32;
while(l<r)
{
ll mid=(l+r)>>1;
if(check(l,mid))
{
r=mid;
}
else l=mid+1;
}
findans(r);
return;
}
int main ()
{
IOS;
while(cin>>n)
solve();
}