题目翻译:
n个社团派发传单,有a,b,c三个参数,派发的规则是,派发给序号为a,a+c....a+k*c,序号要求是小于等于b
这其中,有一个学生只收到了奇数传单,要求找出这个学生的编号与得到的传单数目
思路:
可以知道奇数的编号只有一个。设区间1-x有答案编号,则区间1-x的个数和一定是奇数。
故,可以去二分这个区间端点,判断这个区间和(时间复杂度是 O(n) )。
如果是奇数,那么所求的人肯定在左区间,否则在右区间,这样二分下去找到答案。
代码:
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
using namespace std;
const int N=2e5+10;
struct PW{
ll a,b,c;
}a[N];
int n;
bool check(ll mid){
ll re=0;
for(int i=1;i<=n;i++){
ll s=min(mid,a[i].b);
if(s>=a[i].a){
re+=(s-a[i].a)/a[i].c+1;
}
}
if((re&1)==1){
return 1;
}
else{
return 0;
}
}
int main(){
guo312;
while(cin>>n){
for(int i=1;i<=n;i++){
cin>>a[i].a>>a[i].b>>a[i].c;
}
ll l=1,r=inf;
while(l<r){
ll mid=l+r>>1;
if(check(mid)){
r=mid;
}
else{
l=mid+1;
}
}
ll ans=0;
for(int i=1;i<=n;i++){
if(l>=a[i].a&&l<=a[i].b){
if((l-a[i].a)%a[i].c==0){
ans++;
}
}
}
if((ans&1)==1){
cout<<l<<" "<<ans<<endl;
}
else{
cout<<"DC Qiang is unhappy."<<endl;
}
}
return 0;
}