Codeforces Round 970 (Div.3)

A.Sakurako's Exam

算法:模拟

具体思路:

a个1,b个2 ,使他们的和为 0 ;

规律:

1.当两个数中,一个数不存在时,另一个数的个数必须要有偶数个

2.当1有偶数个时,2可以有奇数个或者是偶数个

3.当1有奇数个时,如何都不满足;

反思:不要着急,慢慢想

AC Code
#include <bits/stdc++.h>
using namespace std;

int n,a,b;

int main() {
	scanf("%d",&n);

	while(n--) {
		scanf("%d%d",&a,&b);

		if(a == 0) {
			if(b % 2) puts("NO");
			else puts("YES");
		}
		else if(b == 0){
			if(a % 2) puts("NO");
			else puts("YES");
		}
		else if(a % 2) puts("NO");
		else puts("YES");
	}
	return 0;
}

B.Square or Not

算法:模拟

具体思路:

1.首先读入的字符串长度是否能够成正方形

n != sqrt(n) * sqrt(n)

2.枚举字符串找是否满足条件;

边界上的值是否为1,里面的是否为 0,即可

字符串到矩阵的转换 s[(i-1) * sqrt(n) + j]

反思:

还是需要多做题,需要经验值

AC Code
#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;

int T,n;
char a[N];

void solve() {
	scanf("%d",&n);
	scanf("%s",a+1);

	int len = sqrt(n);

	if(n != len * len) {
		puts("No");
		return;
	}

	for(int i = 1; i <= len; i++) {
		for(int j = 1; j <= len; j++) {
			int op = 0;
			//边界上值全部为 1
			if(i == 1 || i == len || j == 1 || j == len) op = 1;
			if((a[(i-1) * len + j] - '0' )!= op) {
				puts("No");
				return;
			}
		}
	}
	puts("Yes");
	return;
}
int main() {
	scanf("%d",&T);

	while(T--) {
		solve();
	}
	return 0;
}

C. Longest Good Array

算法:贪心

具体思路:

1.题目要求:数组时递增的且相邻的元素之间的差也是递增的

贪心的令相邻的间隔最小且递增

第一个数为 L, 第 $n + 1$ 个数为 $ L + n (n + 1)/2 <= R $

通过二分查找 n ;

知识点:1+2+3+...+n = n * (n+1)/2

反思:
没想到等差数列

AC Code
#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;

int T;
int a,b;

void solve() {
     scanf("%d%d",&a,&b);
     
     int len = b - a ;
     
     //二分查找 n的值 
     int l = 0, r = 1e9;
     while(l < r)
	 {
     	int mid = l + r + 1 >> 1;
     	if(1LL* mid * (mid + 1) / 2 <= len) l = mid;
     	else r = mid - 1;
	 }
     printf("%d\n",l + 1);
}
int main() {
	scanf("%d",&T);

	while(T--) {
		solve();
	}
	return 0;
}

D.Sakurako's Hobby

算法: dfs

具体思路:

同一个置换环上的点可以相互到达,并查集合并维护置换环上的点

ans[N] : 存放每一个 i 能够到达黑色格子的数量

1.对于每一个i, i--> p[i] ;

如果p[i]是黑色,那么 cnt ++;

2.dfs(a[p[i]]) i = p[i];

dfs找环,当跳到的格子是已经访问过的说明我们已经找到环了,返回达到黑色格子的数量 cnt;

反思:

没有理解题面 i--> p[i] , 即 i = p[i] ;

AC Code
#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;

int T,n;
int a[N];
string s;
bool vis[N];
int ans[N];
int cnt ;

int dfs(int x){
	if(vis[x]){
		return cnt;
	}
	vis[x] = 1;
	if(s[x] == '0') cnt ++;
	ans[x] = dfs(a[x]);
	
	return cnt;   
}
void solve(){
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
	
	s = ""; //字符串的初始化
	string tmp ;
	cin >> tmp;
	s = " " + tmp;
	
	memset(ans,-1,sizeof ans);
	
	for(int i = 1; i <= n; i++){
		if(ans[i] == -1){
			cnt = 0;
			memset(vis,0,sizeof vis);
			ans[i] = dfs(i);
		}
	} 
	
	for(int i = 1; i <= n; i++){
		cout << ans[i] << " ";
	}
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin >> T;
	while(T--){
		solve();
		cout << endl;
	} 
	
	return 0;
} 

E.Alternating String

算法:动态规划

具体思路:

1.状态定义:
f1[i][j] : 前i个字母当中奇数位上字母j出现的次数
f2[i][j] : 前i个字母当中偶数位上字母j出现的次数

2.状态存储:

根据当前位置的奇偶性,来存放当前位置上字母

之后再累加前面字符串中对应的奇/偶数位上该字母出现的次数

3.状态计算:

我们分字符串长度为奇数和偶数的情况;

由于题目要求字符串长度为偶数,因此如果字符串长度为奇数时,我们需要使用操作1,来删除一个字符,使得字符串长度为偶数

偶数时就不用使用操作1

首先讨论一下字符串长度为偶数的情况,因为他比较简单

状态存储时把所有奇/偶位置上对应的字符出现的个数存好了

枚举26个小写字母,各自选取出现次最多的字符

f1[n][j]: 前n个字符中奇数位上字符j出现的次数

f2[n][j]: 前n个字符中偶数位上字符j出现的次数

n - f1[n][j] - f2[n][j]

字符串长度为奇数时,我们先枚举要删除的点

当删除偶数位上的字符j,
字符j的个数:前面奇数位上字符j的个数 + 后面偶数位上字符j存放的个数 - 前i个位置上字符j出现的个数

当删除奇数位上的字符j
那么字符j的个数:前面偶数位上字符j的个数 + 后面奇数位上字符j存放的个数 - 前i个位置上字符j出现的个数

如: ababa ,n = 5, 删除第三位上的字符a,最终序列的奇数位是这个点前面的奇数位和后面的偶数位

反思:
动态规划掌握的不行啊不行

AC Code
#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10;

int T,n;
char s[N];
int f1[N][26],f2[N][26];

//f1[i][j] 前i个数奇数位的字符为j 的个数
//f2[i][j] :前i个数偶数位上字符j的个数

void solve() {
	scanf("%d",&n);
	scanf("%s",s + 1);

	for(int i = 1; i <= n; i ++) 
	{
		//保证当前位置开始时是清空的
		for(int j = 0; j <= 25; j++)
			f1[i][j] = f2[i][j] = 0;

		//根据当前位置的奇偶性来存储相应的字符
		if( i & 1) f1[i][s[i] - 'a'] = 1;
		else f2[i][s[i]-'a'] = 1;

		for(int j = 0; j <= 25; j ++) {
			f1[i][j] += f1[i-1][j];   //奇数位上 j 字符出现的次数累加
			f2[i][j] += f2[i-1][j];   //偶数位上 j 字符出现的次数累加
		}
	}

	int ans = 0x7fffffff; 
	if(n & 1)   //如果长度为奇数时
	{ 
		//先枚举删除哪一个点
		for(int i = 1; i <= n; i++) {
			for(int j = 0; j <= 25; j++)
				for(int k = 0; k <= 25; k ++) 
				{
					int x = f1[i-1][j] + f2[n][j] - f2[i][j]; //删除偶数位的j字符 
					int y = f2[i-1][k] + f1[n][k] - f1[i][k]; //删除奇数位的j字符 
					ans = min(ans,n - 1 - x - y);
				}

		}
		printf("%d\n",ans + 1);
	} else {
		for(int i = 0; i <= 25; i++) 
			for(int j = 0; j <= 25; j++) 
				ans = min(ans, n - ( f1[n][i] + f2[n][j]));
		
		printf("%d\n",ans);
	}
}
int main() {
	
	scanf("%d",&T);
	while(T--) {
		solve();
	}
	return 0;
}

F.

算法:

具体思路:

反思:

AC Code

G.

算法:

具体思路:

反思:

AC Code

H.

算法:

具体思路:

反思:

AC Code

posted @   LTphy  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示