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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)