您的位置:首页 > 其它

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

2014-01-18 21:18 344 查看
昨天的 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: