HDU - 4768 Flyer 二分答案 or 异或

The new semester begins! Different kinds of student societies are all trying to advertise themselves, by giving flyers to the students for introducing the society. However, due to the fund shortage, the flyers of a society can only be distributed to a part of the students. There are too many, too many students in our university, labeled from 1 to 2^32. And there are totally N student societies, where the i-th society will deliver flyers to the students with label A_i, A_i+C_i,A_i+2*C_i,…A_i+k*C_i (A_i+k*C_i<=B_i, A_i+(k+1)*C_i>B_i). We call a student "unlucky" if he/she gets odd pieces of flyers. Unfortunately, not everyone is lucky. Yet, no worries; there is at most one student who is unlucky. Could you help us find out who the unfortunate dude (if any) is? So that we can comfort him by treating him to a big meal! 

Input

There are multiple test cases. For each test case, the first line contains a number N (0 < N <= 20000) indicating the number of societies. Then for each of the following N lines, there are three non-negative integers A_i, B_i, C_i (smaller than 2^31, A_i <= B_i) as stated above. Your program should proceed to the end of the file. 

Output

For each test case, if there is no unlucky student, print "DC Qiang is unhappy." (excluding the quotation mark), in a single line. Otherwise print two integers, i.e., the label of the unlucky student and the number of flyers he/she gets, in a single line. 

Sample Input

2
1 10 1
2 10 1
4
5 20 7
6 14 3
5 9 1
7 21 12

Sample Output

1 1
8 1

题意:有n个社团,第i个社团会给  编号a[i]+k*c[i] (a[i]+k*c[i]<=b[i]&&a[i]+(k+1)*c[i])发一个宣传,现在要你求出

哪一个编号收到的宣传数为奇数,并且输出这个编号收到的宣传数  这个可以二分答案,而且题目说明最多只有一个编号会收到奇数个宣传

假设 一组数为    4 2 5 6 8 2 当二分的时候,编号为mid的时候,如果小于等于mid的编号宣传数前缀和是奇数,就减少mid,如果是偶数就加大mid,最后就会二分到5那个位置的编号,最后再求一下那个编号收到的宣传数就好

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstdlib>
#include<deque>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int len=2e4+5;
const ll mod=998244353;
const ull seed=131;
ll a[len],b[len],c[len];
ll ans;
int n;
int solve(ll mid)
{
	ll sum=0;
	for(int i=0;i<n;++i)
	{
		ll m=min(mid,b[i]);
		if(m>=a[i])
			sum+=(m-a[i])/c[i]+1;
	}
	int x=sum%2;
	return x;
} 
int main()
{	
	while(~scanf("%d",&n))
	{
		for(int i=0;i<n;++i)scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
		ll sum=0;
		for(int i=0;i<n;++i)
			sum+=(b[i]-a[i])/c[i]+1;
		if(sum%2==0)printf("DC Qiang is unhappy.\n");
		else 
		{
			ll l=0,r=1ll<<32,mid;
			while(l<r)
			{
				mid=(l+r)/2;
				if(solve(mid))r=mid;
				else l=mid+1;
			}
			ll ans=0;
			for(int i=0;i<n;++i)
				if(r<=b[i]&&r>=a[i]&&r%c[i]==a[i]%c[i])ans++;
			printf("%lld %lld\n",r,ans);
		}
	}
}

异或就是暴力了      一个数异或和0异或偶数次为0,异或奇数次为那个数,暴力就可

但是这个题目如果是极限数据   n==10000 a[i]都为1,c[i]都是1, b[i]都是1<<31 就会超时了,数据不行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstdlib>
#include<deque>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int len=2e4+5;
const ll mod=998244353;
const ull seed=131;
int a[len],b[len],c[len];
int main()
{	
	int n;
	while(~scanf("%d",&n))
	{
		int ans=0;
		for(int i=0;i<n;++i)scanf("%d%d%d",&a[i],&b[i],&c[i]);
		for(int i=0;i<n;++i)
			for(int j=a[i];j<=b[i];j+=c[i])
				ans^=j;
		if(!ans)cout<<"DC Qiang is unhappy.\n";
		else
		{
			int num=0;
			for(int i=0;i<n;++i)
				for(int j=a[i];j<=b[i];j+=c[i])
					if(j==ans)num++;
			printf("%d %d\n",ans,num);
		}
		
	}
}

猜你喜欢

转载自blog.csdn.net/hutwuguangrong/article/details/86514916