2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛(部分题解,自己的答案)

题目地址:http://oj.saikr.com/contest

文章目录

  • 前言
  • 一、B题 ERROR?
    • 1.题目
    • 2.思路
    • 3.代码
  • 二、E题 吃利息
    • 1.题目
    • 2.思路
    • 3.代码
  • 三、G题 MP4
    • 1.题目
    • 2.思路
    • 3.代码
  • 四、I题 展览
    • 1.题目
    • 2.思路
    • 3.代码
  • 五、I题 礼物
    • 1.题目
    • 2.代码
  • 总结


前言

本人的话,对于算法不太会,这次也只ac了3题,记下来用于自己使用


一、B题 ERROR?

1.题目

2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛(部分题解,自己的答案)_第1张图片

2.思路

因为题目要求最小的eps,我们稍微分析一下题目就可以发现只要当前搜索到的eps满足条件,
更大的eps肯定也满足该条件,所以我们可以考虑二分来搜索最小的eps;
然后b(i)的两个边界值为a(i)+eps和a(i)-eps;
我们可以让前面的b(i)全部通过贪心搜索成最小的,
例如先把b(1)=a(1)-eps,但这里要注意的是b是正整数序列,
所以这里如果b(1)<0的话,就得让b(1)=1;
剩下的序列的话,最好能让b(i)只比b(i-1)大1,
如果不能的话,让b(i)=a(i)-eps试试

3.代码

#include
using namespace std;

#define ll long long
#define int long long
const int N=2e6+10;
int n,a[N],b[N];
bool check(int eps){
    for(int i=1;i<=n;i++) b[i]=a[i];
    b[1]-=eps;
    b[1]=max(b[1],1LL);
    for(int i=2;i<=n;i++){
        if(b[i]+eps<=b[i-1]) return false;
        if(b[i]-eps>b[i-1])
            b[i]-=eps;
        else{
            if(b[i]+eps>b[i-1])
                b[i]=b[i-1]+1;
            else return false;
        }
    }
    return true;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int left=0,right=1e9+10;
    while(left<right){
        int mid=(left+right)>>1LL;
        if(check(mid)){
            right=mid;
        }else{
            left=mid+1;
        }
    }
    cout<<right;
    return 0;
}

二、E题 吃利息

1.题目

2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛(部分题解,自己的答案)_第2张图片

2.思路

简单模拟题

3.代码

#include
using namespace std;

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int li_xi=n/10;
        if(li_xi>5){
           n+=10;
        }else{
            n+=(li_xi+5);
        }
    }
    cout<<n<<endl;
    return 0;
}

三、G题 MP4

1.题目

2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛(部分题解,自己的答案)_第3张图片

2.思路

比赛时候的思路:
	打算直接直接定义一个sort比较的cmp仿函数,但明显复杂度过高,TLE了,
后来想的思路:
	因为只用找字典序前五十个最小的,所以我们可以直接用dfs跳跃搜索,
	定义dfs(left,right,num)的搜索函数,
	即在[left,right]中搜索,具体注释看代码

3.代码

#include
using namespace std;

#define IOS                                                                                                            \
   ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ll long long
#define int long long

int sum,n;
//搜索[l,r]内的k个数
void dfs(int l,int r,int k){
    if(r>n) r=n;//调整数据范围
    for(int i=l;i<=r;i++){
        //这里因为dfs每次向下搜索都是扩大十倍搜索的,所以当如果当前被搜索的这个
        //的数不是左边界且能被10整除,说明该数前还有更小的数能够被搜索到
        if(i!=l&&i%10==0)
            return ;
        sum++;
        if(sum<=k){
            cout<<i<<".mp4"<<endl;
            if(sum==k)//搜索到想要搜索到的个数
                return ;
        }
        if(i*10<=n){
            dfs(i*10,i*100-1,k);
        }
    }
}
signed main(){
    IOS //解绑加快输入输出速度
    cin>>n;
    dfs(1,9,50);
    return 0;
}

/*超时代码*/

四、I题 展览

1.题目

2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛(部分题解,自己的答案)_第4张图片

2.思路

现在的话还是没有思路,因为自己一开始想的是递归求最大值,
就是下步选与不选该值异或,具体看代码
但是不知道怎么剪枝降低复杂度,TLE了,自己好菜qaq

3.代码

/*超时代码,正确代码待加*/
#include
using namespace std;

int ans=0,n;
int a[50];
void dfs(int val,int k){
    if(k==n+1){
        ans=max(ans,val);
        return ;
    }
    dfs(val,k+1);//下一步数不选
    dfs(val ^ a[k],k+1); //下一步选
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    dfs(0,0);
    cout<<ans<<endl;
    return 0;
}

五、I题 礼物

1.题目

2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)-正式赛(部分题解,自己的答案)_第5张图片

2.代码

#include
using namespace std;

bool cmp_max(int x,int y){
	return x > y;
}
int main(){
    int n,m;
    cin>>n;
    vector<int> vec;
    for(int i=0;i<n;i++){
        cin>>m;
        vec.push_back(m);
    }
    sort(vec.begin(),vec.end(),cmp_max);
    cout<<vec.front()<<endl;
    return 0;
}

总结

总的来说,虽然这次自己只AC了3.5道题目,但相比上一次只做了个签到题,还是有进步的,虽然依旧很菜,哈哈哈,继续努力,剩下的题目自己再学会再加上,算法虐我千百遍,我待算法如初恋(不是)。

你可能感兴趣的:(算法比赛题解,算法,c++)