第六周周报

文章分析了几道来自Codeforces竞赛的编程题目,涉及贪心策略、温度调整、末尾0的优化、数组操作和区间交换,展示了如何通过逻辑分析和代码实现解决这些问题。
摘要由CSDN通过智能技术生成

第一题:Login - Codeforces

题目大意:
给定一个温度范围 [l,r] 以及参数 x ,给定初始温度a和目标温度b,求最少次数将初始温度a变为目标温度b的操作数,每次切换温度必须保证温度变化大小大于等于x。

解题思路:

(贪心!!!)
显然只有五种可能的答案:0、-1、1、2、3。

即要么无需操作,要么无解,要么最多只需要三步。

当a == b时,输出0;

if(abs(a-b)>=x)只需要一步输出1;

两步:先向l或者r方向移动,然后反向移动到b。

三步:先向r/l方向移动,然后再向l/r方向移动,再移动到b。

操作的前提是移动的时候不超过l和r。所以判断a、b和l、r之间的差值即可。

(其实这题很简单,当时没写出来是真没有想到只有0、-1、1、2、3这五种可能,还以为会有其他更多方案的操作数,所以就没有想出来)

题解:

#include<bits/stdc++.h>
using namespace std;
int l,r,x,a,b;
void solve(){
    cin>>l>>r>>x>>a>>b;
    if (a==b){
        cout<<0<<endl;
        return;
    }
    if (abs(a-b)>=x){
        cout<<1<<endl;
        return;
    }
    else{
        if (a<b){
            if (a-l>=x){cout<<2<<endl;return;}
            if (r-b>=x){cout<<2<<endl;return;}
            if (r-b<x&&a-l<x&&r-a>=x&&b-l>=x){cout<<3<<endl;return;}
        }
        else if (a>b){
            if (b-l>=x){cout<<2<<endl;return;}
            if (r-a>=x){cout<<2<<endl;return;}
            if (r-a<x&&b-l<x&&a-l>=x&&r-b>=x){cout<<3<<endl;return;}
        }
    }
    cout<<-1<<endl;
}
int main()
{
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    return 0;
}

第二题:Login - Codeforces

题意:给定一个n和m,k的取值范围在1~m,求出最大的n*k并满足有最多的末尾0。

思路:首先10 = 2*5,所以要使末尾有0,首先必须出现2和5,所以我们先分解n,看一下n有多少个5,多少个2,假设n分解之后有4个2,1个5,它本身1个2和1个5相乘等于10,所以剩下3个2,那么此时,k就先补3个5,既5*5*5 = 125,如果此时k还没有超出范围的话,就继续乘10,如果乘10后超出范围了,就在1~9之间相乘,找到最大的那个k。如果k在补5的时候超出范围了,比如m = 26,我们就不能5*5*5了,只需要k = 5*5 = 25即可

///代码题解一
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,k;
//要使由多个0则可使2*5=10就会有一个0,就看两个数能由多少个2*5的组合组成
void solve(){
    cin>>n>>m;
    ll a=n;
    int cnt2=0,cnt5=0;
    while(a%2==0){//计算n可由多少个2组成
        cnt2++;
        a/=2;
    }
    a=n;
    while(a%5==0){//计算n可由多少个5组成
        cnt5++;
        a/=5;
    }
    k=1;
    while(cnt2>cnt5&&k*5<=m&&cnt2--)  k*=5;//将5与2配对,更新k;
    while(cnt2<cnt5&&k*2<=m&&cnt5--)  k*=2;//将2与5配对,更新k;
    while(k*10<=m){//若配对完还能凑出10就继续更新k;
        k*=10;
    }
    cout<<m/k*k*n<<endl;
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t=1;
    cin>>t;
    while (t--){
        solve();
    }
    return 0;
}
/代码题解二
#include<bits/stdc++.h>
#include<iostream>
#include<cmath>
typedef long long ll;
using namespace std;
const int N = 2e5+10;
const int mod = 1e9+7;
ll a[N],b[N],c[N];
void solve(){
    ll n,m;
    cin >> n >> m;
    ll k=1;
    int c2=0,c5=0;
    ll nn = n;
    while(nn%2==0)
    {
        c2++;
        nn/=2;
    }
    nn=n;
    while(nn%5==0)
    {
        c5++;
        nn/=5;
    }
    int d = abs(c2-c5);
    if(c2>c5)
    {
        while(d--&&k*5<=m)
        {
            k*=5;
        }
    }
    else
    {
        while(d--&&k*2<=m)
        {
            k*=2;
        }
    }
    while(k*10<=m)
    {
        k*=10;
    }
    for(int i=1;i<=10;i++)
    {
        if(k*i>m)
        {
            k*=(i-1);
            break;
        }
    }
    cout << n*m/k*k << endl;
}
int main()
{
    int t=1;
    cin >> t;
    while(t--) solve();
    return 0;
}

第三题:Login - Codeforces

题面:1dbd610e8302467280494bae072ae446.png

题意:给你一定数量的a,b。两个a+1个b或者1个a+2个b 都可以合成一个宝石,问最多合成多少个宝石

思路:特判a==0||b==0的时候生成0个宝石;当a或b两倍的数量比b或a少,则最多能生成a或b个宝石;当a!=b的时候,a-2*n=b-n推出n=a-b;

(当时没写出来是因为没太弄懂各种情况!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a,b;
int ans,num;
void solve(){
    cin>>a>>b;
    ans=0;
    if (a==0||b==0){cout<<0<<endl;return;}
    if (a*2<=b) {cout<<a<<endl;return;}
    if (b*2<=a) {cout<<b<<endl;return;}
    if (a!=b){//当a!=b时
        if (a>b){
            num=a-b;
            ans+=num;
            a-=num*2;
            b-=num;
        }
        if (a<b){
            num=b-a;
            ans+=num;
            b-=num*2;
            a-=num;
        }
    }
///此时a==b;
    num=a/3;
    ans+=num*2;
    a%=3,b%=3;
    if (a>1&&b>0||b>1&&a>0){
        ans+=1;
    }
    cout<<ans<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    int t=1;
    cin>>t;
    while(t--)solve();
    return 0;
}

第四题:Login - Codeforces

题面:

bfe76393d53b4ce680755c629b5d05bb.png

题意:是否可以将一个串,分成至少两个部分,使得前一个部分的数字大小小于后面的。

思路:就是一个水题,只要将其分成两部分即可,(没写出来因为没看懂题目(;´༎ຶД༎ຶ`) 

题解:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
    int n;
    string s;
    cin >> n >> s;
    if(n==2 && s[0]>=s[1] ){//特判当n=2的时候,如果前一个比后一个大则不能
        cout<<"NO"<<endl;

    }
    else{
        cout<<"YES"<<endl;
        cout<<"2"<<endl<<s[0]<<" "<< s.substr(1, s.size())<<endl;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int t=1;
    cin>>t;
    while(t--)solve();
    return 0;
}

第五题:

题面:

845d48c7cb414f9194e718aa33be39ec.jpg

 题意:定义一个数组a[x]=1,其余数组都为0,每次给定m个区间,在这个区间内的任何两个数可以进行交换,问操作m次以后区间里面最多有多少个可以等于1。

题解:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e9+10;
int n,m,x;
int l,r;
void solve(){
    cin>>n>>x>>m;
    l=x,r=x;
    int a,b;
    for (int i = 1; i <= m; ++i) {
        cin>>a>>b;
        if (b<l||a>r){continue;}
        l=min(l,a);
        r=max(r,b);
    }
    cout<<r-l+1<<endl;

}
int main()
{
    ios::sync_with_stdio(false);
    int t=1;
    cin>>t;
    while(t--)solve();
    return 0;
}
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值