A.Not a Substring
题意:
定义正规括号对为“()”、“()()”、“(())”此类的可以匹配的括号对,如”)(“是不正则的,现在输入给你一个指定括号序列,询问你是否能构造出一个两倍长度的括号序列,做到构造括号序列不包含所给括号序列。s为所给括号序列长度
分析:
将‘(’视作1,‘)’视作0,发现如果括号序列不严格单调递减,即类似于“(((())”=111100,那就可以构造为“()()()()()()”,若不为不严格单调序列,即类似于“())(”=1001,那就构造为“(((())))”
代码:
#include <stdlib.h>
#include <iostream>
#include<cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include<iomanip>
#include<queue>
#include<stack>
#define int long long
#define endl '\n'
void solve()
{
string s;
cin>>s;
int n=s.length();
int a[n];
if(s=="()")
{
cout<<"NO"<<endl;
return ;
}
else
{
cout<<"YES"<<endl;
}
for(int i=0;i<n;i++)
{
if(s[i]=='(')a[i]=1;
else a[i]=0;
}
bool flag=0;
for(int i=0;i<n-1;i++)
{
if(a[i]<a[i+1])
{
flag=1;
break;
}
}
if(flag==0)
{
for(int i=0;i<2*n;i++)
{
if(i%2==0)cout<<'(';
else cout<<')';
}
cout<<endl;
}
else
{
for(int i=0;i<n;i++)
{
cout<<'(';
}
for(int i=0;i<n;i++)
{
cout<<')';
}
cout<<endl;
}
}
signed main()
{
cin.tie(nullptr)->sync_with_stdio(0);
int turn=1;
cin>>turn;
while(turn--)
{
solve();
}
}
B.Fancy Coins
题意:
有一件价值m的商品,Monocarp想买它,Monocarp有两种硬币,一种面值为1(有a1个),一种面值为k(有ak个);Monocarp只会用刚好m元的价格购买这个商品。题目告诉我们m,k,a1,ak;问我们还额外需要几个硬币才能购买这个商品
分析:
我们的想法肯定是如果能面值为k的硬币的话就用它(即总钱数没超过m且硬币数量够),换言之我们要尽量多的使用面值为k的硬币,然后再用面值为1的硬币补上缺口,从这里我们分类讨论,下面用if else来写hhh
if(已有的面值为k的硬币数量大于等于最大需要的数量)//这里指的是我们最大需要多少个,即需要m/k个
{
if(已有的面值为1硬币数量大于等于最小需要的数量)//最小需要多少个,即为m%k,也就是 m-m/k
{
输出0,因为都已经满足 }
else //已有的面值为1硬币数量小于最小需要的数量
{
输出面值为1的硬币缺少的数量
}
}
else //已有的面值为k的硬币数量小最大需要的数量 就是说我们的k面值的硬币不够
{
if(已有的面值为1硬币数量大于等于最小需要的数量)面值为1的硬币有多,可以尽量去替换缺少的面值为k的硬币
{
输出(面值为k的硬币缺少的个数 - (面值为1的硬币多出来的个数/k))
}
else //面值为1的硬币也不够
{
输出(面值为1的硬币缺少的数量 + 面值为1的硬币缺少的数量)
}
}
代码:
#include <stdlib.h>
#include <iostream>
#include<cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include<iomanip>
#include<queue>
#include<stack>
#define int long long
#define endl '\n'
void solve()
{
int m,k,a,b;
cin>>m>>k>>a>>b;
int z=0;
if((m/k-b)<=0)
{
if((a-(m%k))>=0)
{
cout<<"0"<<endl;
}
else
{
cout<<(m%k)-a<<endl;
}
}
else
{
if((a-(m%k))>=0)
{
cout<<max(z,(m/k-b)-(a-(m%k))/k)<<endl;
}
else
{
cout<<max(z,(m/k-b)+(m%k)-a)<<endl;
}
}
}
signed main()
{
cin.tie(nullptr)->sync_with_stdio(0);
int turn=1;
cin>>turn;
while(turn--)
{
solve();
}
}
C. Game on Permutation
题意:
爱丽丝和鲍勃轮流走同一个棋子,棋盘是一个条形的(输入的一个数组),上面的数字对应了这个位置的值。其中爱丽丝走第一步并且第一步只能放置棋子而不能移动棋子,每次移动只能将棋子移动到当前位置的左边且数值比当前位置数值小的地方,比如213,3可以移动到2或者1,1不可以移动到2因为2比1大。如果谁先不能移动,谁就赢了。如果对于一个位置,爱丽丝先将棋子放在这里,她一定可以获胜,则我们称这个位置为必胜位置,请输出必胜位置的个数。
分析:
用常用的思维考虑,对于必胜的情况,我们尝试着去思考必败的情况再找反之的条件,我们首先研究,怎么样会让对方赢,那么当左边没有可选数字时,或者对方下一步走到必胜状态时,他就赢了,那么反之思考我们获胜的条件就是左边有可选数字并且对方下一步无法走到必胜状态,我们就必胜了。那么我们只需要记录左边可选数字的最小值,和左边必胜状态的最小值就可以了,(因为如果连最小的都走不了,那肯定没法走了),通过一个for循环找到必胜位置的个数
代码:
#include <stdlib.h>
#include <iostream>
#include<cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include<iomanip>
#include<queue>
#include<stack>
#define int long long
#define endl '\n'
void solve()
{
int n;
cin>>n;
int a[n];
for(int i=0;i<n;i++)
{
cin>>a[i];
}
int x=1e9+10,y=a[0],ans=0;
//x记录当前数左边最小必胜状态的值,y记录当前数左边最小可选数的值
for(int i=1;i<n;i++)
{
if(a[i]>y&&a[i]<x)//必胜情况 ,a[i] > y 表示左边有可选状态,a[i] < x 表示左边无可走的必胜状态
{
x=min(x,a[i]);//x表示前面可以转移的最小必胜状态值
ans++;
}
y=min(y,a[i]);//y表示前面可以转移的最小值
}
cout<<ans<<endl;
}
signed main()
{
cin.tie(nullptr)->sync_with_stdio(0);
int turn=1;
cin>>turn;
while(turn--)
{
solve();
}
}
优快云:陪你一起cf
bilibili:acmer--沈幼楚
知乎:与你cf