程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 4768 Flyer(二分)

hdu 4768 Flyer(二分)

編輯:C++入門知識

題目鏈接:hdu 4768 Flyer


題目大意:給出n,表示有n種廣告,然後每種廣告有a,b,c三個值,表示分發的對象有a,a+c,a+2*c...a+k*c.(a+k*c <= b && a+(k+1)*c > b).然後收到廣告數為奇數的同學是不幸運的,如果沒有人收到廣告數為奇數,輸出DC Qiang is unhappy!,否則輸出不幸運同學的序號以及收到的廣告數,樣例確保至多一人為奇數。


解題思路:二分,首先要確定,如果在[l,r]這個區間上有一個人的廣告數為奇數,那麼總的廣告數也為奇數。所以可以二分首先確定l~r這個區間上有一個人是不幸運的,然後二分mid = (l+r)/2,如果mid~r這個區間為奇數的話,l = mid+1,否則r = mid。然後就是統計一個區間中的廣告數時要注意,並不是區間長度len,len/d+1(d為當前考慮的廣告分發間距)就是廣告數,要與分發的起始位置相關聯。


#include 
#include 
#include 
#include 

using namespace std;
typedef long long ll;
const int N = 20005;
const ll INF = (1<<31)-1;
struct ad {
	ll a, b, c;
}d[N];
int n, m;
ll l, r;

void init () {
	l = INF; r = 0;

	for (int i = 0; i < n; i++) {
		cin >> d[i].a >> d[i].b >> d[i].c;
		l = min(l, d[i].a);
		r = max(r, d[i].b);
	}
}

ll judge (ll k) {
	ll c = 0;
	for (int i = 0; i < n; i++) {
		ll x = min(r, d[i].b) - d[i].a;
		ll y = min(k, d[i].b) - d[i].a;
		if (x >= 0)
			c += (x/d[i].c + 1);
		if (y >= 0)
			c -= (y/d[i].c + 1);

	}
	return c;
}

ll solve () {
	while (l < r) {
		ll mid = (l+r) / 2;
		if (judge(mid)&1) l = mid+1;
		else r = mid;
	}
	return l;
}

int main () {
	while (scanf("%d", &n) == 1) {
		init ();
		if (judge(l-1)&1) {
			ll ans = solve(), c = 0;
			for (int i = 0; i < n; i++) {
				if (ans > d[i].b) continue;
				ll x = ans - d[i].a;
				if (x >= 0&&x%d[i].c == 0) c++;
			}
			cout << ans << " " << c << endl;
		} else
			printf("DC Qiang is unhappy.\n");
	}
	return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved