Codeforces Round #262 (Div. 2)

A.Vasya and Socks

题意:有n个袜子,每天穿一双晚上扔掉,每m天再买一双。求一共能连续穿多少天?

题解:给n分成 n/m*m和n-n/m*m两部分递归计算。

B.Little Dima and Equation

题意:x = b·s(x)a + c,s(x)是x的各位数字和。输入a、b、c,求使等式成立的X。

题解:枚举每个S(x),求对应的x。x的范围是0-81,不到为什么他们hack了好多72的。

C.Present

题意:有n盆花,每盆花的高度为a[i]。每天可以选一段连续的的序号的花浇灌,浇灌的花高度+1。连续浇m天,求最矮的花的高度。

题解:二分答案 + check()。用mi记录当前位置前面影响当前位置的浇灌次数,队列q记录影响的位置序列。当前位置需要高度大于mi,则当前位置需要浇灌mi-x天,mi+=x。若队首的与当前位置的距离大于w,则减去队首的浇灌次数。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <string>
using namespace std;
#define For(i,a) for(i=0;i<a;i++)
#define Foru(i,a,b) for(i=a;i<=b;i++)
#define Ford(i,a,b) for(i=a;i>=b;i--)
#define clr(ar,vel) memset(ar,vel,sizeof(ar))
#define PB push_back
typedef long long ll;
const int maxint = 0x7fffffff;
const ll maxll = 1LL<<60;
int a[100010];
int b[100010];
int n, m, w;
queue<int> q;
int check(ll x){
//	cout << x << endl;
//	cout << "###################" << endl;
	ll mi = 0;
	int cnt = 0, fn;
	while(q.size()) q.pop();
	for(int i = 0; i < n; i ++)	b[i] = x-a[i];
	for(int i = 0; i < n; i ++){
		
		if( q.size()) {
			fn = q.front();
			if( i - fn >= w ) {
				mi -= b[fn];
				q.pop();
			}
		}
//		cout << mi << ' ' << b[i] << ' ' << i << ' ' << fn << endl;
		if( b[i] - mi > 0) {
			int t = b[i] - mi;
			mi += b[i]-mi;
			b[i] = t;
			q.push(i);
			cnt += b[i];
		}
		if( cnt > m ) return 0;
	}
//	cout << x << ' ' << cnt << endl; 
	return cnt <= m;
}
int main(){

	ll sum;
	while(~scanf("%d%d%d",&n,&m,&w)){
		sum = 0;
		for(int i = 0; i < n; i ++) {
			scanf("%d",a+i);
			sum += a[i];
		}
		ll l, r, mid;
		l = 1; r = 2000000000;
		while( l < r){
			mid = (l+r)/2;
			if( check(mid)){
//				cout << "mid   " << mid << endl;
				l = mid+1;
			}
			else r = mid;
		}
		printf("%d\n",l-1);
	}
	return 0;
}


D.Little Victor and Set

题意:输入l、r、k,求一个集合set,使得1 <= set.size <= k,队列元素连续异或的结果最小。

题解:1、k=1时,l最小。2、k=2时,i^(i+1)=1、3、5……,求最小值。3、k >= 4时,连续四个异或是0。

4、 k=3时,当时没想明白,看题解也看了半天才弄懂。i%2 == 0时,i^(i+1) == 1。若结果等于0,则三个数异或等于0。

1:3个数 l<=x<=y<=z<=r,因为x^y^z == 0,z的二进制最高位为1,则y的最高位为1,x的最高为等于0.
2:若x的第二位为0,因为异或结果为0,则x,y的第二位同时为0或1.x、y、z更接近所以x,y的第二位为0。重复1.
3:若x的第二位为1,因为异或结果为零,y<z,所以y的第二位为0,z的第二位为1.
即:
x: 011……1			1 -> mn <<= 1, mn++; 
y: 101……1 		2 -> mx <<= 1, mx-1;
z: 110……0 		3 -> mx ;

代码:

<span style="font-size:12px;">#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <string>
using namespace std;
#define For(i,a) for(i=0;i<a;i++)
#define Foru(i,a,b) for(i=a;i<=b;i++)
#define Ford(i,a,b) for(i=a;i>=b;i--)
#define clr(ar,vel) memset(ar,vel,sizeof(ar))
#define PB push_back
typedef long long ll;
const int maxint = 0x7fffffff;
const ll maxll = 1LL<<60;
int check3(ll l, ll r, ll k){
	ll mn = 1;
	ll mx = 3;
	while( mx <= r){
		if( mn >= l){
			cout << 0 << endl;
			cout << 3 << endl;
			cout << mn << ' ' << mx-1 << ' ' << mx << endl;
			return 0;
		}
		mn <<= 1;
		mx <<= 1;
		mn ++;
	}
	if( k >= 4) for(ll i = l+3; i <= r; i ++){
		if( (i^(i-1)^(i-2)^(i-3)) == 0){
			cout << 0 << endl;
			cout << 4 << endl;
			cout << i << ' ' << i-1 << ' ' << i-2 << ' ' << i-3 << endl;
			return 0;
		}
	}
	ll mi = l;
	for(ll i = l+1; i <= r; i ++){
		if( (i^(i-1)) == 1) {
			cout << 1 << endl;
			cout << 2 << endl;
			cout << i << ' ' << i-1 << endl;
			return 0;
		}
		if( (i^(i-1)) <= mi) mi = i^(i-1);
	}
	for(ll i = l+1; i <= r; i ++){
		if( (i^(i-1)) == mi) {
			cout << mi << endl;
			cout << 2 << endl;
			cout << i << ' ' << i-1 << endl;
			return 0;
		}
	}
	cout << l << endl;
	cout << 1 << endl;
	cout << l << endl;
	return 0;
}
int main(){
	ll n, m, k;
	int flag;
	while(cin >> n >> m >> k){
		flag = 0;
		if(k == 1 || m-n == 0) {
			cout << n << endl;
			cout << 1 << endl;
			cout << n << endl;
		}
		else if( k == 2 || m-n == 1){
			ll mi = n;
			for(ll i = n+1; i <= m; i ++){
				if( (i^(i-1)) == 1) {
					cout << 1 << endl;
					cout << 2 << endl;
					cout << i << ' ' << i-1 << endl;
					flag = 1;
					break;
				}
				if( (i^(i-1)) <= mi) mi = i^(i-1);
			}
			if( !flag ) for(ll i = n+1; i <= m; i ++){
				if( (i^(i-1)) == mi) {
					cout << mi << endl;
					cout << 2 << endl;
					cout << i << ' ' << i-1 << endl;
					flag = 1;
					break;
				}
			}
			if( !flag ) {
				cout << n << endl;
				cout << 1 << endl;
				cout << n << endl;
			}
		}
		else if( k >= 3 || m-n >= 2) {
			check3(n, m, k);
		}
	}
	return 0;
}</span>


E.Roland and Rose

题意:

题解:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值