A. MEX Destruction
翻译:
龙 Evirir 溜进了一个巫师的城堡,发现了一个神秘的装置,他们玩耍的本能使他们玩弄(摧毁)了它...
埃维龙发现了一个由 n 个非负整数组成的数组
。
在一次操作中,他们可以选择 a 的一个非空子数组∗ b,并用整数 mex(b)† 取而代之。他们希望多次使用这一操作,使 a 只包含零。可以证明,在问题的约束条件下,这总是可行的。
所需的最少运算次数是多少?
思路:
对于一个不存在0的子数组进行mex会得到0。
都只有0时,运算次数为0。
当只有1段无0子数组时,运算次数为1。
当有1段以上的子数组时,运算次数为2。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;
void solve(){
int n,ans=0;
cin>>n;
vector<int> a(n+1,0);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
if(a[i]!=0&&a[i-1]==0)ans++;
}
if(ans>1)ans=2;
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 中间填保留几位小数,不填默认
// cout.precision();
int t;cin>>t;
while (t--) solve();
}
B. pspspsps
翻译:
猫会被ppspsps吸引,但埃维里尔作为一条高贵的龙,只会被有奇怪特定要求的ppspsps吸引...
给定一个长度为 n 的字符串 s=
由字符 p、s 和 .(点)组成,判断是否存在长度为 n 的排列∗ p,使得对于所有整数 i(1≤i≤n):
- 若
为 p,则 [
]构成一个长度为 i 的排列;
- 如果
是 s,那么 [
]构成一个排列(长度为 n-i+1);
- 如果
为 .,则没有额外的限制。
思路:
符号p代表左侧(l)的所有数字为排列,而s代表右侧(r)的所有数字为排列。当存在p在s左侧的情况(不包括两端)时为NO
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;
void solve(){
int n;
string s;
cin>>n;
cin>>s;
int l = -1,r = -1;
for (int i=0;i<n;i++){
if (s[i]=='s') l = i;
if (r==-1&&s[i]=='p') r = i;
}
if (l!=-1 && r!=-1){
if (l==0||r==n-1){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}else{
cout<<"YES"<<endl;
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 中间填保留几位小数,不填默认
// cout.precision();
int t;cin>>t;
while (t--) solve();
C. MEX Cycle
翻译:
龙 Evirir 有很多朋友。他们有 3 个朋友!比普通龙多一个。
给你一个整数 n、x 和 y。有 n 条龙围成一个圆圈。龙的编号为 1、2、......、n。对于每个 i(1≤i≤n),龙 i 与龙 i-1 和 i+1 为好友,其中龙 0 定义为龙 n,龙 n+1 定义为龙 1。此外,龙 x 和龙 y 也是彼此的朋友(如果它们已经是朋友,则不会有任何变化)。请注意,所有好友关系都是相互的。
输出 n 个非负整数
,使得每条龙 i(1≤i≤n)的下列条件成立:
- 让
为龙 i 的朋友。则
.∗
思路:
分类讨论:
- x,y相邻
- n为偶数(even)
- 使用010101循环
- n为奇数(odd)
- 下标1使用2,之后使用01循环
- x,y不相邻
- x到y的两条路径中所蕴涵的元素数量都为奇数
- 从x到y两路径都使用01循环,0开始(包括x),对于下标y赋值为2
- x到y的两条路径中所蕴涵的元素数量都为偶数
- x到y的两路径一条使用01循环,一条使用10循环(都不包括x),对于下标x赋值为2,y赋值为3
- x到y的两条路径中所蕴涵的元素数量为一奇数,一偶数
- 从x到y两路径都使用01循环,0开始(包括x),下标y赋值为2
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;
void solve(){
int n,x,y;
cin>>n>>x>>y;
vector<int> a(n+1);
if (x+1==y || (x>1&&x-1==y) || x==1&&y==n){
if (n%2==0){
int cnt = 0;
for (int i=1;i<=n;i++){
a[i] = cnt;
cnt^=1;
}
}else{
int cnt = 0;a[1] = 2;
for (int i=2;i<=n;i++){
a[i] = cnt;
cnt ^= 1;
}
}
}else{
if ((y-x-1)%2 && (n-(y-x+1))%2){
int cnt = 0;
for (int i=x;i<y;i++){
a[i] = cnt;
cnt ^= 1;
}
cnt = 0;
for (int i=x;i!=y;i = (i==1 ? n : i-1)){
a[i] = cnt;
cnt ^= 1;
}
a[y] = 2;
}else if ((y-x-1)%2==0 && (n-(y-x+1))%2==0){
int cnt = 1;
for (int i=x+1;i<y;i++){
a[i] = cnt;
cnt ^= 1;
}
cnt = 0;
for (int i=(x==1 ? n : x-1);i!=y;i = (i==1 ? n : i-1)){
a[i] = cnt;
cnt ^= 1;
}
a[x] = 2;
a[y] = 3;
}else{
int cnt = 0;
for (int i=x;i<y;i++){
a[i] = cnt;
cnt ^= 1;
}
cnt = 0;
for (int i=x;i!=y;i = (i==1 ? n : i-1)){
a[i] = cnt;
cnt ^= 1;
}
a[x] = 0;
a[y] = 2;
}
}
for (int i=1;i<=n;i++){
if (i!=1) cout<<" ";
cout<<a[i];
}cout<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 中间填保留几位小数,不填默认
// cout.precision();
int t;cin>>t;
while (t--) solve();
}
D. Shift + Esc
翻译:
龙 Evirir 在玩弄了某种装置并被抓住后,决定好好利用他们的魔法技能--扭曲现实以快速逃脱!
给你一个网格,网格中有 n 行、m 列非负整数和一个整数 k。让 (i,j) 表示从上到下第 i 行和从左到右第 j 列中的单元格(1≤i≤n, 1≤j≤m)。对于每个单元格 (i,j),整数 ai,j 都写在单元格 (i,j) 上。
您最初位于 (1,1),想要移动到 (n,m)。您只能向下或向右移动。也就是说,如果您在 (i,j),您只能移动到 (i+1,j) 或 (i,j+1)(如果存在相应的单元格)。
在开始移动之前,您可以多次执行以下操作:
- 在 1 到 n 之间选择一个整数 i,将第 i 行向左循环移动 1。形式上,对于所有整数 j(1≤j≤m),使
变为
。
注意,开始移动后不得进行任何操作。
从(1,1)移动到(n,m)后,设 x 为移动前进行的操作次数,y 为写在已访问单元格(包括(1,1)和(n,m))上的整数之和。那么成本定义为 kx+y。求从 (1,1) 移动到 (n,m) 的最小成本。
思路:
考虑当前i行向左第shift次后的结果tmp,dp[i][j]都可能由(上面的元素)(dp[i-1][j]+当前的元素+当前行向左移动的次数)或(左面的元素)(dp[i][j-1]+当前的元素+当前行向左移动的次数)构成,
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
// using pll = pair<ll,ll>;
void solve(){
ll n,m,k;cin>>n>>m>>k;
vector<vector<ll>> a(n+1,vector<ll>(m)),dp(n+1,vector<ll>(m+1,1e18));
for (ll i=1;i<=n;i++){
for (ll j=0;j<m;j++){
cin>>a[i][j];
}
}
dp[0][0] = 0;
for (ll i=1;i<=n;i++){
for (ll shift=0;shift<m;shift++){
vector<ll> tmp(m,1e18);
for (ll j=0;j<m;j++) tmp[j] = dp[i-1][j]+a[i][(j+shift)%m];
for (ll j=0;j<m;j++) tmp[j] = min(tmp[j],tmp[(j+m-1)%m]+a[i][(j+shift)%m]);
for (ll j=0;j<m;j++) dp[i][j] = min(dp[i][j],tmp[j]+k*shift);
}
}
cout<<dp[n][m-1]<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 中间填保留几位小数,不填默认
// cout.precision();
ll t;cin>>t;
while (t--) solve();
}