【链接】:https://ac.nowcoder.com/acm/contest/73760
比赛时间:2024-01-28 19:00-21:00
赛制:IOI
前提:本人真的是小白,题解也只是为了自己的复盘,E、F由于这两题知识点(dp)还没学习到,所以现在无法对其进行补题。
目录
A.小红的删字符
知识点:语法
难度:200
思路:俗称“签到题”,直接输出字符串第一个和最后一个字符即可
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;cin>>s;
s.erase(1,1);
cout<<s;
return 0;
}
复盘:比赛时未想到最优解,运用erase函数有点想太多了
重新写了一个更符合思路的代码
直播讲解的思路:签到题。直接输出第一个字符和最后一个字符即可
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;cin>>s;
cout<<s[0]<<s[2];
return 0;
}
B.小红的正整数
知识点:贪心,排序
难度:500
思路:先排序,再考虑第一位是否为0,如果是就向后挪
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
int n;cin>>n;
int i=0;
while(n>0)
{
a[i]=n%10;
n/=10;
i++;
}
sort(a,a+i);
if(a[0]==0)
{
int idx=0;
for(int j=0;j<i-1;j++)
{
if(a[j]==0&&a[j+1]!=0)
{
idx=j;
break;
}
}
int temp=a[idx+1];
for(int j=idx;j>=0;j--)
{
a[j+1]=a[j];
}
a[0]=temp;
}
for(int j=0;j<i;j++)
cout<<a[j];
return 0;
}
复盘:比赛时的思路过于乱了,且代码量有点大
重新写了一个更精简点的代码
直播讲解的思路:首先将最小数位的非零移动到首位,剩下的数位从小到大输出即可
另外本题数据范围较小,也可以暴力从小到大枚举,check是否符合重排标准
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;cin>>s;
sort(s.begin(),s.end());
if(s[0]=='0')
{
for(int i=1;i<s.size();i++)
{
if(s[i]!='0')
{
swap(s[0],s[i]);
break ;
}
}
}
cout<<s;
return 0;
}
C.小红的构造回文
知识点:枚举
难度:900
思路:由于给的字符串就是回文,你可以直接将前半部分与后半部分进行交换,然后将交换完后的字符串与最初进行比较,判断是否相同
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
string s;cin>>s;
string s1,s2,str;
int len=s.size();
s1=s.substr(0,len/2);
if(len%2==0)
{
s2=s.substr(len/2,len/2);
str=s2+s1;
}
else
{
s2=s.substr(len/2+1,len/2);
str=s2+s[len/2]+s1;
}
if(str==s)cout<<-1;
else cout<<str;
return 0;
}
复盘:我这个思路就是需要求字符串的长度奇还是偶,要进行灵活变动
直播讲解的思路:由于给定的是回文串,我们直接枚举前半部分,找到任意一个相邻不同的位置,交换这两个字符即可(需要在对称的位置也做一次交换操作)
D.小红整数操作
知识点:数学/二分
难度:1400
思路:先求最大公约数,将x,y互质,再进行模拟,求解
比赛时,由于IOI赛制,就输出1,骗到15分
#include <bits/stdc++.h>
using namespace std ;
#define int long long
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
signed main()
{
int x,y,l,r;
cin>>x>>y>>l>>r;
int k=gcd(x,y);
x/=k,y/=k;
if(x==1)
{
return cout<<max((r-l*y)/y+1,1LL*0),0;
}
int ret=0;
for(int c=1;x*c<=r&&y*c<=r;c++)
{
if(x*c>=l&&y*c>=l)ret++;
}
cout<<ret;
return 0 ;
}
直播讲解的思路:首先可以将x和y的所有公因数除掉,形成x和y互素的情况,接下来就只需要考虑乘法了
E.小红树上染色
知识点:树形dp
难度:1700
直播讲解的思路:我们定义dp[i][0/1]代表i号节点不染色/染色的子树合法方案数,dfs中使用后序遍历,当子树所有信息都被求出来了以后,我们根据当前节点的颜色讨论不同情况的合法方案转移即可。
F.小红叒战小紫
知识点:期望dp
难度:2200
比赛时,由于IOI赛制,就输出0,骗到11.67分
直播讲解的思路:我们定义dp[i][j]为:小红剩余恰好j个1血量怪物时,需要进行的回合数。一共有4种情况:两个人都抽到1(无事发生,转移到dp[i][j]),两个人都抽到2(无事发生,转移到dp[i][j]),小红抽到1小紫抽到2(转移到dp[i-1][j]),小红抽到2小紫抽到1(转移到dp[i][j-1]),我们列方程后即可推出转移方程:
dp[i][j]=(1-p2-p3)*dp[i][j]+p2*dp[i-1][j]+p3*dp[i][j-1]+1
(p2+p3)*dp[i][j]=p2*dp[i-1][j]+p3*dp[i][j-1]+1