第三天打卡 Educational Codeforces Round 73 (Rated for Div. 2)

A:题意:给一串数列,两个相等能够合并,问是否能凑成2048
从211开始,往下遍历,每一次如果有数字,那么*=2,看最后加和是否大于等于需要的即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int q;
int n;
const int N = 1e3 + 10;
ll s[N];
map<ll, ll>mp;
int main()
{
	q = read();
	while (q--)
	{
		mp.clear();
		n = read();
		upd(i, 1, n)s[i] = read();
		upd(i, 1, n)
		{
			up(j, 0, 40)
			{
				if ((1ll << j)&s[i])
					mp[j]++;
			}
		}
		ll sum = 0;
		ll need = 1;
		int flag = 1;
		dwd(i, 11, 0)
		{
			if (mp[i]+sum >= need)
			{
				flag = 0;
				break;
			}
			else
			{
				sum *= 2;
				sum += mp[i] * 2;
				need *= 2;
			}
		}
		if (!flag)
		{
			printf("yes\n");
		}
		else printf("no\n");
	}
}

B:题意:给一个棋盘,放象棋 的马,问最大互相攻击。
dfs即可。


C:二分一下即可。cf老套路了。


D:dp
题意:给一串序列a,要使得a序列相邻两项不相等。使ai上升1需要花费bi,问最小花费。
我么能够发现,除了第一个和最后一个,中间每一个被夹在了两个之间,那么,意味着中间每一个不能取的数字至多两个,所以我们假设x不能取,那么我们加1,变成x+1,如果x+1还是不能取,变成x+2,x+2一定是不和相邻元素相同的数字。
所以我们就有了dp策略,每一个数字至多上升2,便能完全使得数组没有相邻相同元素。
令dp[i][j]表示第i个上升j的时候哦,前面所有数字满足题意的最小花费。
就有转移
(ai-1+k!=ai+j) dp[i][j]=dp[i-1][k]+j*bi

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int q;
int n;
const int N = 3e5 + 10;
ll a[N], b[N];
ll dp[N][5];
int main()
{
	q = read();
	while (q--)
	{
		n = read();
		upd(i, 1, n)
			a[i] = read(), b[i] = read();
		upd(i, 1, n)
			upd(j, 0, 2)dp[i][j] = 1e18 + 1;
		upd(i, 1, n)
		{
			upd(j, 0, 2)
			{
				upd(k, 0, 2)
				{
					if (a[i - 1] + j == a[i] + k)continue;
					dp[i][k] = min(dp[i][k], dp[i - 1][j] + 1ll*k * b[i]);
				}
			}
		}
		ll minans = 1e18 + 1;
		upd(j, 0, 2)
			minans = min(dp[n][j], minans);
		printf("%lld\n", minans);
	}
	return 0;
}

E题:题意:
给01字符串,0的位置能被替换成为1,现在x和y博弈,x先手,每一次x能反转a个0到1,y能反转b个零到1,当到某个人的回合时,如果某个人没有再能反转的输。
首先有个重要的条件,a>b,这就意味着,有小区间,b能覆盖而a不能。我们以此入手。
1.当存在区间,a>区间长度>=b,这就意味着只能b取覆盖而a不能。如果x想赢得比赛,那么x一定在最后会取覆盖长度为a的区间,那么这个时候y如果再上一步,就将这个区间覆盖掉,那么x必输,因为只剩下a>len>=b的区间。
2.如果>=2b的区间多于两个,那么就可以转换成为上述情况,因为x先手可能破坏掉一个,那么y后手至少有一个2b的区间,这个时候只要选择覆盖掉后这个区间剩余长度在a~b之间即可,也就是第一种情况,那么x必输。
3.如果2b区间为零。那么意味着所有区间长度都在2b>len>=a,那么只需要判断所有区间的数量即可,因为相当于x和y每一次覆盖掉一个区间后,这个区间就再也不能覆盖新的了。
4.如果2b有一个区间。那么我们遍历这个区间长度,每一次取a,判断左右两边的情况,看x是否能赢。左右两边首先不能出现上面1,2的情况不然必输。所以只能是第三种情况,在判断奇偶即可。
那么我们最后看一看如果2
b<a了,看第一种情况,没有变化,第二种情况,还是没有变化。第三种情况,如果2b的区间为零,a区间那么就为零,x必输。
第四种情况,如果有2
b区间,这个区间就是a>len>2*b>=b,回到第一种情况。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 3e5 + 10;
int q;
int a, b;
string s;
int cnt[N];
int main()
{
	q = read();
	while (q--)
	{
		a = read(), b = read();
		cin >> s;
		int n = s.size();
		int top = 0;
		bool flag = 0;
		memset(cnt, 0, sizeof(cnt));
		up(i, 0, n)
		{
			if (s[i] == '.')
			{
				if (!flag)++top, flag = 1;
				cnt[top]++;
			}
			else flag = 0;
		}
		int cnta = 0; int cntb = 0; int cntc = 0;
		int pos;
		upd(i, 1, top)
		{
			if (cnt[i] >= b && cnt[i] < a)cntc = 1;
			if (cnt[i] >= 2 * b)cntb++,pos=i;
			if (cnt[i] >= a)cnta++;
		}
		if (cntc)
		{
			printf("no\n");
			continue;
		}
		if (cntb >= 2)
		{
			printf("no\n");
			continue;
		}
		if (cntb == 0)
		{
			if (cnta & 1)printf("yes\n");
			else printf("no\n");
			continue;
		}
		bool ok = 0;
		upd(i, 0,  cnt[pos]-a)
		{
			int left = i;
			int right = cnt[pos] - i - a;
			if (left >= b && left < a || right >= b && right < a)continue;
			if (left >= 2 * b || right >= 2 * b)continue;
			int temp = (cnta + (left >= a) + (right >= a));
			if (temp % 2)
				ok = 1;
		}
		if (ok)printf("yes\n");
		else printf("no\n");
	}
	return 0;
}
posted @ 2019-12-08 10:36  LORDXX  阅读(161)  评论(0编辑  收藏  举报