CodeForces Round 224 B (二分或图论) C (等差数列 水题)

19 篇文章 0 订阅

昨天的 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值