Codeforces Round 863 (Div. 3)

题解报告

基本的一些理解和问题都在注释中
A:Insert Digit
找到第一个小于输入数字的数的位置塞进去就好了,可以细推,但是粗略想想也能知道

#include <bits/stdc++.h> using namespace std; int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int T;cin>>T; while(T--) { string s; int len,num; cin>>len>>num>>s; int flag=1; for(int i=0;i<len;i++)//遇到第一个小的就输出,等于的不行。一定等于的话不一定是最优秀的, { if(flag&&s[i]-'0'<num)cout<<num,flag=0; cout<<s[i]; } if(flag)cout<<num; cout<<endl; } return 0; }

B:Conveyor Belts
考虑离中间点的距离大的,然后判断各个点位在第几层,判断层数的距离就行了
注意离中间点的距离的计算就行了

#include <bits/stdc++.h> using namespace std; int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int T;cin>>T; while(T--) { int N,X1,Y1,X2,Y2; cin>>N>>X1>>Y1>>X2>>Y2; N=N/2; int DX1=N-X1;if(DX1<0)DX1=-DX1-1; int DY1=N-Y1;if(DY1<0)DY1=-DY1-1; int DX2=N-X2;if(DX2<0)DX2=-DX2-1; int DY2=N-Y2;if(DY2<0)DY2=-DY2-1; cout<<(int)abs(max(DX1,DY1)-max(DX2,DY2))<<endl; } return 0; }

C:Restore the Array
这道题目既可以通过找规律,也可以通过模拟来进行构造
不过我没有写出来,菜是原罪,哎~~
画图!!!画图!!!画图!!!画图看关系是真的很重要

#include <bits/stdc++.h> using namespace std; const int maxn=2e5+10; int num[maxn]; // int main(void)//方法一:不怎么好想 // { // ios::sync_with_stdio(false); // cin.tie(0);cout.tie(0); // int T;cin>>T; // while(T--)//取两个的间隔的max组成的数组是不可能存在(小-大-小)这种结构的,所以 // {//在两个数中每次取小的,就可以在原数组的推导中每次都可以通过取大的取出那个数,因为一个数不是比右边的大,就是比左边的大,或者相等。 // //一个数不可能同时比两边的大,所以这种方法一定可以按照顺序把每个数都取一遍。 // //对于边界的值,如果直接放上B数组的边界,这样就可以保证所有的数都可以取到, // //边界的值可以放B数组边界的值,这样就可以保证不管是先取还是后取,都会有第一个数和最后一个数。 // int N;cin>>N; // for(int i=0;i<N-1;i++)cin>>num[i]; // cout<<num[0]<<' '; // for(int i=0;i<N-2;i++)cout<<min(num[i],num[i+1])<<' '; // cout<<num[N-2]<<endl; // } // return 0; // } int main(void) { ios::sync_with_stdio(false);//比较容易想到 cin.tie(0);cout.tie(0); int T;cin>>T; while(T--) { //不断的塞入数组进行模拟 int N;cin>>N; for(int i=0;i<N-1;i++)cin>>num[i]; vector<int> ans; ans.push_back(num[0]); int cnt=1; for(int i=1;i<N-1;i++) { if(cnt==i){//决定别人的时候 if(ans.back()<num[i])cnt++,ans.push_back(0); ans.push_back(num[i]); cnt++; }else{//决定自己的时候 if(ans.back()<num[i])cnt++,ans.push_back(num[i]); } } if(ans.size()!=N)ans.push_back(0); for(int i=0;i<N;i++)cout<<ans[i]<<' '; cout<<endl; } return 0; }

D:Umka and a Long Flight
想像每增加一个正方形后,长度为1的正方形可以怎么变换就行了
长度为1的正方形可以怎么位移?水平方向上的移动是怎么样的,可以怎么移动?竖直方向是怎么样的?

#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn=50; ll Fib[maxn]; void init() { Fib[0]=1;Fib[1]=1; for(int i=2;i<maxn;i++) Fib[i]=Fib[i-1]+Fib[i-2]; } int main(void) { int T;cin>>T; init(); while(T--) { ll N,X,Y; cin>>N>>X>>Y; int flag=N&1; for(int i=N;i>=1;i--)if((i&1)!=flag&&X-Fib[i]>=1)X-=Fib[i]; for(int i=N;i>=1;i--)if((i&1)==flag&&Y-Fib[i]>=1)Y-=Fib[i]; if(X==1&&Y==1)cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }

E:Living Sequence
去掉一个数后就是九进制数,考虑每个数的组成后拆分就行了

#include <bits/stdc++.h> #define ll long long using namespace std; int main(void) { int T;cin>>T; while(T--)//就是个十进制化为九进制而已 { ll N;cin>>N; ll ans=0,cnt=0; while(N) { ans+=pow(10,cnt)*((N%9)>=4?((N%9)+1):(N%9)); N/=9; cnt++; } cout<<ans<<endl; } return 0; }

G1:Vlad and the Nice Paths (easy version)
线性dp时,考虑自己这个位置是怎么被处理的,从操作的角度来考虑,既可以被除去,也能成为一部分
多多画图,看看状态之间是怎么转移的,各种操作会导致怎么样的状态

#include <bits/stdc++.h> using namespace std; const int maxn=1e2+10; const int MOD=1e9+7; int dp[maxn][maxn];//当前位置,有j个长度为K的序列的个数。 int C[maxn][maxn]; int num[maxn]; void init()//获取组合数的经典递推 { for(int i=0;i<maxn;i++) { C[0][i]=1; for(int j=1;j<=i;j++) C[j][i]=(C[j-1][i-1]+C[j][i-1])%MOD; } } int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); init(); int T;cin>>T; while(T--) { memset(dp,0,sizeof(dp)); int N,K;cin>>N>>K; for(int i=1;i<=N;i++)cin>>num[i]; if(K==1)//注意这里后面利用到了组合数,所以这里要先特判一下 { cout<<1<<endl; continue; } dp[0][0]=1; for(int i=1;i<=N;i++) { dp[i][0]=1; for(int j=1;j<=N/K+1;j++)//对所有的情况进行更新。 { int now=1; for(int k=i-1;k>=1;k--)//枚举如果num[i]作为新的K位的时候的所有的可能性。 { if(num[k]==num[i])//利用组合算进行统计。 { now++; if(now>=K)dp[i][j]=(dp[i][j]+(1LL*dp[k-1][j-1]*C[K-2][now-2])%MOD)%MOD; } } dp[i][j]=(dp[i][j]+dp[i-1][j])%MOD;//如果num[i]这位不算,那么它的可能就是前面的可能,这里要加上 } } for(int i=N/K+1;i>=0;i--)//从长度最大的开始枚举。 { if(dp[N][i]) { cout<<dp[N][i]<<endl; break; } } } return 0; }

G2:Vlad and the Nice Paths (hard version)
由于不需要每个长度的,所以只要记录最长的就行了,每次对最长的进行更新

#include <bits/stdc++.h> using namespace std; const int maxn=5e3+10; const int MOD=1e9+7; int dp[maxn],Max[maxn],num[maxn];//dp记录这个位置i前(包括这个位置i)长度为Max[i]的情况的个数, //Max[i]记录这里可以有的满足题目条件的最长的分区数。 //num记录原数组 int C[maxn][maxn]; void init() { for(int i=0;i<maxn;i++) { C[0][i]=1; for(int j=1;j<=i;j++) C[j][i]=(C[j-1][i-1]+C[j][i-1])%MOD; } } int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); init(); int T;cin>>T; while(T--) { memset(dp,0,sizeof(dp)); memset(Max,0,sizeof(Max)); int N,K;cin>>N>>K; for(int i=1;i<=N;i++)cin>>num[i]; dp[0]=1; for(int i=1;i<=N;i++) { int now=1; for(int j=i-1;j>=1;j--)//num[i]作为dp[i]的最后一个的情况。 { if(num[i]==num[j]) { now++; if(now==K)Max[i]=Max[j-1]+1;//可以扩充的最长的 if(now>=K) { if(Max[i]!=Max[j-1]+1)break;//不是最长的了 dp[i]=(dp[i]+(1LL*dp[j-1]*C[K-2][now-2])%MOD)%MOD; } } } //证明i之前最长的不是i开始的,所以i这里的组合不是要的,置为0 if(Max[i]<Max[i-1]) { dp[i]=0; Max[i]=Max[i-1]; } //i可以继承i-1的集合,所以直接加上dp[i-1]的情况。 //不作为最后一个考虑的情况。 if(Max[i]==Max[i-1])dp[i]=(dp[i]+dp[i-1])%MOD; } cout<<dp[N]<<endl; } return 0; }

F不太会,就不写了
掉分了,失败的一场比赛,哎~~


__EOF__

本文作者WUTONGHUA02
本文链接https://www.cnblogs.com/WUTONGHUA02/p/17302586.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   WUTONGHUA02  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示