题意说的是:
给你 a[1~n] , b[1~n] , c[1~n];
其中对任意的若满足 a[i]+c[i]<=b[i]; vis[ a[i]+c[i] ]++;
若找一个奇数,还是很容易的,用异或运算来处理。清楚明白;
但是正解应该是二分区间;
示例二中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 2 2 2 1 2 0 0 2 0 0 0 0 0 0 2 0
答案就是8 1 //第八个同学,拿了一张传单
二分区间就是给定了(区间中左端点 和 右端点给你,其中里面 多少张 传单是可以算出来的)
二分区间是需要找到奇数的那个区间,虽然不好想,可以看一看代码就会更加清楚了。
方法一:异或
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int L=20005;
ll a[L],b[L],c[L];
int main()
{
int i,j,n;
while(~scanf("%d",&n))
{
for(i=0;i<n;i++)
scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
ll ans=0,cnt=0;
for(i=0;i<n;i++)
for(j=a[i];j<=b[i];j+=c[i])
ans^=j;
if(ans)
{
for(i=0;i<n;i++)
for(j=a[i];j<=b[i];j+=c[i])
if(ans==j)cnt++;
printf("%lld %lld\n",ans,cnt);
}
else
printf("DC Qiang is unhappy.\n");
}
return 0;
}
方法二: 等差数列+二分区间:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=20010;
ll A[maxn],B[maxn],C[maxn],n;
ll cal(ll mid){
ll sum=0;
for (int i=0;i<n;i++){
ll up=min(mid,B[i]); //每个区间上限 和 mid 比较 确定上限
if (up>=A[i])
sum+=(up-A[i])/C[i]+1;
}
// cout<<mid<<" "<<sum<<endl;
return sum;
}
int main()
{
while(~scanf("%lld",&n)){
for (int i=0;i<n;i++){
cin>>A[i]>>B[i]>>C[i];
}
long long L=0,R=1LL<<31;
while (L<R){
ll mid=(L+R)/2;
if (cal(mid)%2) R=mid;
else L=mid+1;
}
if (L==1LL<<31)
cout<<"DC Qiang is unhappy."<<endl;
else {
while (cal(L)%2==0) L--;
cout<<L<<' '<<cal(L)-cal(L-1)<<endl;
}
}
return 0;
}