首页 > 其他分享 >Codeforces Round 811 (Div. 3)

Codeforces Round 811 (Div. 3)

时间:2023-12-09 17:13:34浏览次数:49  
标签:std 10 int Codeforces len 811 Div include dp

基本情况

ABC秒了。

DE都给了我希望,但都做不下去。

两道题反复横跳,结果最后谁也没做出来。

E还是比D亲切的,先补E吧。

E. Add Modulo 10

做的时候想着说对每个个位数的变化找找规律,但是没有进一步的发现。

实际上就应该从这里下手。

首先共识:相同的两个数经过操作后必然相同。

分析每一个十进制末位,即数经过一次变换后末位会从啥变成啥:

由图得 \(\{a\}\) 中不能同时存在 \(5\) 的倍数和非 \(5\) 的倍数。

若全为 \(5\) 的倍数,将她们的末尾全部操作为 \(0\),判断相等即可。

若全非 \(5\) 的倍数,将她们的末尾全部操作为 \(2\)。由于 \(2\to 4\to 8\to 6\to 2\) 绕一圈后原数会 \(+20\),所以我们判断这些数是否 \(\bmod\ 20\) 同余即可。

#include<iostream>
#include<algorithm>
#include<cstdio>

const int N  = 2e5 + 10;
int n, a[N];

void calc(int& x) {while(x % 10 != 2 && x % 10 != 0) x += x % 10;}

void solve()
{
	std::cin >> n;
	for (int i = 1; i <= n; i++) std::cin >> a[i];
	int cnt = 0;
	for (int i = 1; i <= n; i++) if (a[i] % 5 == 0) cnt++;
	if (cnt > 0 && cnt < n) {std::cout << "NO\n"; return ;}
	for (int i = 1; i <= n; i++) calc(a[i]);
	if(!cnt) for (int i = 1; i <= n; i++) a[i] %= 20;
	for (int i = 2; i <= n; i++) if(a[i] != a[i - 1]) {std::cout << "NO\n"; return ;}
	std::cout << "YES\n";
} 

int main()
{
 	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	int _; std::cin >> _;
	while(_--)solve(); 
	return 0;
}

D. Color with Occurrences

做的时候真的毫无想法。

没想到居然是DP,想必我知道了是DP也做不出来的


由于同一段可以被染色多次,所以最小代价和顺序无关。

可以想到动态规划,设 \(dp[i]\) 为将 \(t\) 的前 \(i\) 个字符都染色的最小代价。

考虑如何进行转移,不妨预处理出 \(len_j\) 表示 \(s_j\) 的长度, \(match[i][j]\) 表示 \(s_j\) 能否匹配字符串 \(t\) 中以位置 \(i\) 结尾,长度为 \(len_{j}\) 的子串。这样就很好转移,对于每个位置 \(i\),考虑每个能够匹配的 \(s_j\),对于每个 \(s_j\),从 \([i-len_j,i]\) 区间内转移。注意:由于染色区间可以不交,所以左端点为 \(i-len_j\) 而不是 \(i-len_j+1\)。由此得到状态转移方程如下:

\[dp[i]=\min_{match[i][j]=1} \{\min_{k=i-len_j}^i dp[k]+1\} \]

在转移的同时记录 \(from[i]\) 和 \(type[i]\) 数组,记录转移到 \(i\) 的状态的染色终点(即方程中的 \(k\))和染色时使用的模板串编号(即方程中的 \(j\))。

注意 \(dp\) 数组初值应为正无穷,若转移完后 \(dp[n]=\infty\),则报告无解,否则使用记录的 \(from[i]\) 和 \(type[i]\) 递归输出方案即可。单组数据时间复杂度 \(\mathcal O(|t|\sum|s_i|)\),可以通过。参考代码如下:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>

const int N = 110;
int dp[N], from[N], ok[N][N];
int len[N], type[N];
std::string s;

void print(int n)
{
	if (n == 0) return;
	print(from[n]);
	std::cout << type[n] << " " << n - len[type[n]] + 1 << std::endl;
	return ;
}

void init()
{
	std::cin >> s; 
	memset(dp, 0x3f, sizeof(dp));
	memset(from, 0, sizeof(from));
	memset(ok, 0, sizeof(ok));
	dp[0] = 0;
}

void solve()
{
	init();
	int n = s.length(), m;
	std::cin >> m;
	s='0'+s;
	for (int i = 1; i <= m; i++)
	{
		std::string temp; std::cin >> temp; len[i] = temp.length();
		for (int j = len[i]; j <= n; j++)
		{
			if (s.substr(j - len[i] + 1, len[i]) == temp) ok[j][i] = 1;
		}
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (!ok[i][j]) continue;
			for (int k = i - len[j]; k < i; k++)
			{
				if (dp[k] + 1 < dp[i])
				{
					from[i] = k, type[i] = j;
					dp[i] = dp[k] + 1;
				}
			}
		}
	}
	if (dp[n] == 0x3f3f3f3f) std::cout << -1 << std::endl;
	else std::cout << dp[n] << std::endl, print(n); 
}

int main()
{
 	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	int _; std::cin >> _;
	while(_--) solve();
	return 0;
}

标签:std,10,int,Codeforces,len,811,Div,include,dp
From: https://www.cnblogs.com/kdlyh/p/17891194.html

相关文章

  • Codeforces Round 913 (Div. 3)
    A.Rook打印出象棋车的下一步usingnamespacestd;voidsolve(){ strings; cin>>s; chara=s[0]; charb=s[1]; set<string>ans; for(chari='1';i<='8';i++){ stringt=""; t+=a; t+=i; ans.insert(t); } for(chari......
  • 【LGR-168-Div.4】洛谷入门赛 #18
    打表过样例题目描述很不幸,你遇到了不负责任的出题人。在某道试题里,共有\(N\)个测试点,组成了\(k\)个Subtask,第\(i\)个Subtask包含\(p_i\)个测试点,第\(j\)个测试点的编号为\(w_{i,j}\)。请注意,一个测试点可能属于多个Subtask。Subtask每个Subtask包含多个测......
  • 可以拖拽缩放的div
    一、HTML代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metahttp-equiv="X-UA-Compatible"content="IE=edge"/><metaname="viewport"content......
  • [ABC254Ex] Multiply or Divide by 2
    [ABC254Ex]MultiplyorDivideby2题意:给定大小为$n$的集合$A$和$B$,你可以对集合$A$中的元素$a_i$进行两种操作,分别为$a_i\leftarrow\lfloor\dfrac{a_i}{2}\rfloor$,和$a_i\leftarrowa_i\times2$。你需要操作集合$A$直至集合$A,B$完......
  • Codeforces Round 894 G
    玩一下样例就能知道这个是和每个seg的最大间隔相关为了好写我们可以直接写成元素间隔这样我们用两个multiset维护元素间隔以及元素即可注意删除的时候我们只删一个值需要删指针还有考虑长度为1的情况multiset<int>st,st1;voidErase(intx){autoit=st1.lower_bound......
  • Codeforces Round 913 (Div. 3)
    CodeforcesRound913(Div.3)比赛链接ROOK题目思路:我没有下过国际象棋,但这个题跟国际象棋真是没有一点关系,就是一个简单的输出代码:#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoidsolve(){//intn;strings;cin>>s;in......
  • CodeForces 1901F Landscaping
    洛谷传送门CF传送门还是很有趣的一道题。场上直接暴拆式子,要维护动态凸包,本来以为是\(\log^2\)的,写着写着发现是\(\log^3\),遂弃。显然梯形面积最小等价于\(y_0+y_1\)最小,而\(y_0+y_1\)最小等价于梯形在\(m=\frac{n}{2}\)处最小。把上凸包建出来,发现过\(x=m......
  • Codeforces Round 913 (Div. 3)
    CodeforcesRound913(Div.3)div3两题新纪录..我再也不喝完酒打cf了A.Rook#include<bits/stdc++.h>//#defineintlonglong#defineendl'\n'usingnamespacestd;intboard[10][10];voidsolve(){strings;cin>>s;intx=s[0]-&#......
  • 【题解】CodeForces 1902F Trees and XOR Queries Again
    传送门:https://codeforces.com/contest/1902/problem/F数据结构题,这里讲两种思路。$ST$表思路:判定“从若干个数中能否取出其中一些,使得异或和为$x$”的问题,第一时间想到线性基,本题要做的显然就是快速求出询问路径上所有数的线性基。两组数的线性基可以合并,方法为“暴力将......
  • Educational Codeforces Round 158 (Rated for Div. 2)
    Preface补题,妈的现在EduE都做不来这搞毛啊A.LineTrip签到#include<cstdio>#include<iostream>#include<utility>#include<vector>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>#include<queue&......