1. 程式人生 > >CodeForces Round 224 B (二分或圖論) C (等差數列 水題)

CodeForces Round 224 B (二分或圖論) C (等差數列 水題)

昨天的 B 題的確有點意思.....

他的題目很含蓄 .... 給你 A 和 C ,C 每秒減 1 ,A 的話給你三個數  b, x, w, 若 b >= x ,b = b - x,否則 a = a - 1, b = w - (x - b)(每秒只完成一個分支)。後面那個式子展開後就發現不管在 if 的哪個分支裡面,b 都是減去 x 的,只是當 b < 0 的時候要加上個 w,所以 k 次操作之後 b 變成了 b - k * x + n * w,n 是讓這個式子大於 0 的最小值。

a = a - k, c = c - n

然後二分答案就可以了。

圖論的話是這樣,因為 b 的範圍是小於 1000 的,可以列舉 b 的可能的數值,然後建立一個狀態轉移的圖,找到迴圈節,然後搞啊搞,這種方法好麻煩,到最後的時候還要判斷最後一秒的時候是否有用。因為當操作 c - 1 的時候, a 也減了 1,這樣就不減少差值,若之前相等的話還要對答案減一。

二分= =,額。

#include<stdio.h>
#include<cmath>
#include<iostream>
using namespace std;

#define LL long long 

LL a,b,w,x,c;

bool OK(LL k)
{
	LL n=(k*x-b)/w;
	if((k*x-b)%w)
		n++;
	if(k-n>=c-a)
		return true;
	return false;
}

int main()
{
	cin>>a>>b>>w>>x>>c;
	LL ub=1e13,lb=-1;
	if(c<=a)
	{
		puts("0");
		return 0;
	}
	while(ub-lb>1)
	{
		LL m=(ub+lb)>>1;
		if(OK(m))
			ub=m;
		else
			lb=m;
	}
	cout<<ub<<endl;
	
}

C 嘛,就是給你 n 個數,讓你判斷有幾個位置可以使得這個數列加一個數之後變成等差數列。

分開考慮。1 和 2 的時候比較特殊,1 可以有無數個, 2 最多可以有三個, 剩下的要麼是 2 個,要麼是 1 個。

最後,要考慮差是 0 的特殊情況,因為這樣的話原來可以放兩個數的位置, 因為相同就變成一個數了。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define LL long long 
LL num[100009];
struct myD
{
	LL pos;
	LL cnt;
	LL w;
}dd[2];

int main()
{
	int n ;
	scanf("%d", &n);
	for(int i = 0; i < n; i++)
		cin >> num[i];
	if(n == 1)
	{
		printf("-1");
		return 0;
	}
	sort(num, num + n);
	if(n == 2)
	{
		LL d = abs(num[1] - num[0]);
		if(d == 0)
		{
			puts("1");
			printf("%d\n", num[0]);
			return 0;
		}
		if(d == 1 || d % 2)
		{
			cout << 2 << endl << num[0] - d << " "<< num[1] + d;
			return 0;
		}
		cout << 3 << endl << num[0] - d << " " << num[0] + (d / 2) << " " << num[1] + d << endl;
		return 0;
	}
	dd[0].w = dd[1].w = -1;
	dd[0].cnt = dd[1].cnt = 0;
	for(int i = 0; i < n - 1; i++)
	{
		LL d = num[i + 1] - num[i];
		if(d == dd[0].w || dd[0].w == -1)
		{
			dd[0].cnt++;
			dd[0].pos = i;
			dd[0].w = d;
		}else if(d == dd[1].w || dd[1].w == -1)
		{
			dd[1].cnt++;
			dd[1].pos = i;
			dd[1].w = d;
		}else
		{
			cout << 0 << endl;
			return 0;
		}
	}
	myD * small, *more;
	small = dd[0].w < dd[1].w ? &dd[0] : &dd[1];
	more = dd[0].w > dd[1].w ? &dd[0] : &dd[1];
	if(small->w == -1)
	{
		if(more->w == 0)
		{
			cout << 1 << endl <<num[0];
			return 0;
		}
		puts("2");
		cout << num[0] - more->w << " " << num[n - 1] + more->w << endl;
		return 0;
	}
	if(more->cnt != 1 || small->w ==0 ||more->w % 2 || more->w / small->w != 2)
	{
		puts("0");
		return 0;
	}
	puts("1");
	cout << num[more->pos] + small->w << endl;
	return 0;
}