Codeforces Round #784 (Div. 4)

D 题

题意 : 所有的序列中所有的颜色最初是白色的,你每次可以使得两个相邻格子染成(RB)或者染成(BR),给你一个已经染好的序列s,问你是否可以从最初所有都是白色序列染成序列s

思路 : 只要染色了,那么必定有R和B,如果只有R没有B,或者只有B没有R就一定是错的,只要有R,并且有B,那就一定可以推出所有的序列,W就相当于  隔板 的作用,考虑一段只用考虑B和R,如果遇到了W就全部重新考虑

#include <bits/stdc++.h>
 
using namespace std;
 
void solve()
{
	int n;string s;cin >> n >> s;
	bool r = false,b = false,f = false;
	for(int i = 0;i < n;i ++ )
	{
		if(s[i] == 'W')
		{
			if(r ^ b) f = true;
			r = false;
			b = false;
			continue;
		}
		else
		{
			if(s[i] == 'B') b = true;
			if(s[i] == 'R') r = true;
		}
	}
	
	if(r ^ b) cout << "NO" << '\n';
	else if(f) cout << "NO" << '\n';
	else cout << "YES" << '\n'; 
}
int main()
{
	int t;cin >> t;
	while(t -- ) solve();
	return 0;
}

E

题目大意: 给你n个只有两个字符组成的字符串,满足 (两个不相同的字符串只有一个共同的字符) ,

一共有多少对?

思路 因为只有两个字符,所以我们可以把字符当成数字来处理,那问题就转化成,询问两个数位只有一位共同的数位 的个数,因为是a 到 k 只有11个字符,所以可以将字符转化成 >= 11 进制的数字,这里是转化成26进制

#include <bits/stdc++.h>
#define int long long
using namespace std;
int c[1000];
 
void solve()
{
	memset(c,0,sizeof c);
	
	int n;cin >> n;
	for(int i = 1;i <= n;i ++ )
	{
		string s; cin >> s;
		c[(s[0] - 'a') * 26 + (s[1] - 'a')]++; 
	}
	int ans = 0;
	for(int i = 0;i <= 26 * 26;i ++ )
	{
		for(int j = i;j <= 26 * 26;j ++ )
		{
			int x1 = i / 26,y1 = i % 26;
			int x2 = j / 26,y2 = j % 26;
			if((x1 == x2) + (y1 == y2) == 1)
			{
				ans = ans + 1ll * (c[i] * c[j]);
			} 
			
		}
	}
	
	cout << ans << '\n';
}
signed main()
{
	int t;cin >> t;
	while(t -- ) solve();
}

F

题目大意: 有两个人 A,B,给你n组蛋糕,第i组的蛋糕数量是a[i],A只能从左到右吃蛋糕,B只能从右到左吃蛋糕,不能跳过某组蛋糕,求A,B吃一样的蛋糕数量下,两个人最多能吃多少组蛋糕

思路 双指针,l,r分别从左到右,从右到左,来移动 . l 相当于A,r 相当于B,固定A吃的数量,然后让B从右到左吃蛋糕,当B吃到的蛋糕和A相等时,记录一下他们此时吃了几组蛋糕.

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
#define cint cin.tie(0)
#define int long long
using namespace std;
 
const int N = 2e5 + 300,mod = 998244353;
int a[N],s1[N],s2[N];
void solve()
{
	int n;cin >> n;
	for(int i = 1;i <= n;i ++ )cin >> a[i];
 
	
	int l = 1,r = n;
	int sumA = 0;
	int sumB = 0;
	int id = 0;
	int cnt = 0;
 
	while(l <= r)
	{
		sumA += a[l];
		cnt++;
		while(sumB < sumA && l < r)
		{
			sumB += a[r];
			--r;
			cnt++;
		}
		
		if(sumB == sumA)id = cnt;
		
		++l;
	}
	
	cout << id << '\n';
	
}
signed main()
{
	ios;cint;
	int t; cin >> t;
	while( t -- ) solve();
	return 0;
}

G 模拟

这道题就是模拟一下就好了

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
#define cint cin.tie(0)
#define int long long
using namespace std;
 
const int N = 210,mod = 998244353;
char a[N][N],b[N][N];
void solve()
{
	int n,m;cin >> n >> m;
	
	for(int i = 1;i <= n;i ++ )
		for(int j = 1;j <= m;j ++ )
			cin >> a[i][j];
			
 
		
	for(int i = 1;i <= n;i ++ )
		for(int j = 1;j <= m;j ++ )
			b[i][j] = '.';
		
		
	for(int i = 1;i <= m;i ++ )
	{
		int cnt = 0;
		
		for(int j = 1;j <= n;j ++ ) // 看看这一列有多少个石头 
		{
			if(a[j][i] == '*')
			cnt++;
			else if(a[j][i] == 'o')
			{
				b[j][i] = 'o';
				
				for(int k = j - 1;k >= j - cnt;k -- ) // 全部变成石头
				{
					b[k][i] = '*';
				}
				
				cnt = 0;
			} 
		}
	
		if(cnt != 0) // 全部落在最下面 
		{
			for(int k = n;k >= n - cnt + 1;k -- ) // 全部变成石头
				{
					b[k][i] = '*';
				} 
		}
		
		
	}
 
	for(int i = 1;i <= n;i ++ )
	{
		for(int j = 1;j <= m;j ++ )	
			cout << b[i][j];
					 
		cout << '\n';
	}
	
	
	
}
signed main()
{
	ios;cint;
	int t; cin >> t;
	while( t -- ) solve();
	return 0;
}

H

题目大意: 你可以进行最多k次的 或 操作,使得a[i] = a[i] % pow(2,j) ,j 的范围是 (0,30) ,然后让所有的a[i] 操作完成以后的数值最大

思路: 二进制下的 操作要使得值最大,最好使得所有的a[i]在二进制下的第i位,全部为1,因为  操作下第i位只要有0   完一定是 0,所以我们要从高位到低位(优先修改能够使得数值最大位数)使得所有的数字在第i位下尽量全部为1, 使得的数字在第i位下为1的操作就是 操作

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false)
#define cint cin.tie(0)
#define int long long
using namespace std;
 
const int N = 2e5 + 100,mod = 998244353;
int a[N],sum[N];
void solve()
{
	int n,k;cin >> n >> k;
	memset(sum,0,sizeof sum);
	for(int i = 1;i <= n;i ++ ) cin >> a[i]; 
	for(int i = 1;i <= n;i ++ )
	{
		for(int j = 30;j >= 0;j -- )
		if(a[i] >> j & 1)
		sum[j]++;
	}
 
//	for(int i = 30;i >= 1;i -- ) s += (1 << i);
//	cout << s << '\n';
//	 
	int ans = 0;
	for(int i = 30;i >= 0;i -- )
	{
		if(sum[i] == n)
		ans += (1 << i);
		else
		{
			if(k >= (n - sum[i]) && k > 0)
			{
			
				k = k - (n - sum[i]);
				ans += (1 << i);
			}
		}
	}
	
	cout << ans << '\n';
	
}
signed main()
{
	ios;cint;
	int t; cin >> t;
	while( t -- ) solve();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值