Codeforces Round 1043 (Div. 3)(A-E)

补题链接:Dashboard - Codeforces Round 1043 (Div. 3) - Codeforces

A. Homework

思路

模拟就行了

代码

cpp 复制代码
void solve(){
    int n;string a;
    cin>>n>>a;
    string t=a;
    a=" "+a;
    int m;string b;
    cin>>m>>b;b=" "+b;
    string s;
    cin>>s;
    int now=1;
    for(int i=0;i<s.size();i++){
        if(s[i]=='D'){
            t=t+b[now];
        }else{
            t=b[now]+t;
        }
        now++;
    }
    cout<<t<<"\n";
}

B. The Secret Number

思路

右边加0就是,即,所以我们遍历一遍看n是否取余为0即可

代码

cpp 复制代码
void solve(){
    int n;
    cin>>n;
    int now=1;
    vi ans;
    for(int i=1;i<=18;i++){
        now*=10;
        int t=now+1;
        if(n%t==0){
            ans.push_back(n/t);
        }
    }
    sort(ans.begin(),ans.end());
    cout<<ans.size()<<"\n";
    for(int x:ans){
        cout<<x<<" ";
    }cout<<"\n";
}

C1. The Cunning Seller (easy version)

思路

我们要保证交易次数最少,因为每次可以交易的西瓜,对于n来说我们只需要每次找到最大的x然后让n来减去,这样就能保证交易次数最少,如果不是每次找到最大的x那么我们应该至少需要3次来抵消掉此次操作,所以我们这样就是最小的交易次数

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;

vi p(50,0);
void init(){
    p[0]=3;
    for(int i=1;i<=30;i++){
        p[i]=(9+i)*pow(3,i-1);
    }
}

void solve(){
    int n;cin>>n;
    int ans=0;
    for(int i=30;i>=0;i--){
        int x=pow(3,i);
        while(n>=x){
            n-=x;
            ans+=p[i];
        }
    }
    cout<<ans<<"\n";
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    init();
    int _=1;
    cin>>_;
    while(_--) solve();
    return 0;
}

C2. The Cunning Seller (hard version)

思路

我们要保证最多k次交易的情况下交易n个西瓜,并且花费金币最少

我们可以从C1的基础上做文章,如果每多两次交易我们可以将西瓜从,西瓜数量不变但是金币的数量却减少了,发现x越大的所省下的金币越少,那么我们便以此为切入点,在C1所求出的最小交易次数的基础上变成k次,每多2次就让最大的x变成3个x-1

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;

vi p(40,0);
vi pw(40,0);
void init(){
    pw[0]=1;
    for(int i=1;i<=25;i++){
        pw[i]=3*pw[i-1];
    }
    p[0]=3;
    for(int i=1;i<=25;i++){
        p[i]=(9+i)*pw[i-1];
    }
    
}

void solve(){
    int n,k;cin>>n>>k;
    if(k>=n){
        cout<<n*3<<"\n";return;
    }
    int cnt=0;
    int tn=n;
    vi ct(40,0);
    for(int i=25;i>=0;i--){
        int x=pw[i];
        while(tn>=x){
            tn-=x;
            cnt++;
            ct[i]++;
        }
    }
    if(k<cnt){
        cout<<"-1\n";return;
    }
    k-=cnt;
    int c=k/2;
    for(int i=25;i>=0;i--){
        if(c){
            if(c<=ct[i]){
                ct[i-1]+=3*c;
                ct[i]-=c;
                c=0;
                break;
            }else{
                ct[i-1]+=3*ct[i];
                c-=ct[i];
                ct[i]=0;
            }
        }else{
            break;
        }
    }
    int ans=0;
    for(int i=0;i<=25;i++){
        ans+=ct[i]*p[i];
    }
    cout<<ans<<"\n";
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    init();
    int _=1;
    cin>>_;
    while(_--) solve();
    return 0;
}

D. From 1 to Infinity

思路

此题我们肯定首先要定位加到某个数x,然后求从1->x的各位数之和以及(x+1)的前几位数相加

1.定位,这并不难实现,9个1位,90个2位,900个3位...,暴力定位即可

2.求1->x的各位数之和,这个学过数位dp的话应该不算太难

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;


int f(int n){       //从0到n的各位数字之和
    if(n<=0) return 0;
    if(n<10) return n*(n+1)/2;
    int x=1;
    int d=0;
    while(x*10<=n){
        x*=10;
        d++;
    }
    int a=n/x;
    int b=n%x;
    int td=d*45*(x/10);
    return a*td+x*a*(a-1)/2+a*(b+1)+f(b);
}

void solve(){
    int k;cin>>k;
    
    //定位k位于那位数的加和上
    int d=1;
    int x=9;
    while(k-d*x>=0){
        k-=d*x;
        d++;
        x*=10;
    }
    int ans=0;
    int n=k/d;
    int r=k%d;
    int now=pow(10,d-1)+n-1;    //求出加到哪个完整的数

    ans+=f(now);
    string s=to_string(now+1);
    for(int i=0;i<r;i++){
        ans+=(s[i]-'0');
    }
    cout<<ans<<"\n";
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    cin>>_;
    while(_--) solve();
    return 0;
}

E. Arithmetics Competition

思路

是个好题,有两种做法

做法一:

我们将a与b数组合成一个数组从大到小排序,对于每次询问x,y,z,我们用cnta表示前z大的中出现了cnta个a数组里面的数,cntb表示出现了cntb个b数组里面的数

1.cnta<=x&&cntb<=y 我们直接输出前z大的和即可

2.cnta>x 也就是我们从a中选择x个数,从b中选择z-x个数,可以保证这样是最大的

3.cntb>y 从b中选择y个数,从a中选择z-y个数

做法二:

我们将a从小到大排序,b从大到小排序,将a与b拼接

这样就形成了一个从小到大再从大到小的一个数组,我们每次询问的目的是找到从区间内选择一个长度为z的子区间求最大的子区间

发现子区间也是从小到大再由大到小的,那么我们就可以尝试用三分查找来找到最大的子区间的位置,进而得到答案

代码

一:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;

struct node{
    int v,id;
};
bool cmp(node x,node y){
    return x.v>y.v;
}

void solve(){
    int n,m,q;
    cin>>n>>m>>q;

    vi a(n+1),b(m+1);
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    sort(a.begin()+1,a.begin()+1+n,greater<int>());
    sort(b.begin()+1,b.begin()+1+m,greater<int>());

    vector<int> sa(n+1),sb(m+1);    //前缀和
    for(int i=1;i<=n;i++) sa[i]=sa[i-1]+a[i];
    for(int i=1;i<=m;i++) sb[i]=sb[i-1]+b[i];

    vector<node> c(1);
    for(int i=1;i<=n;i++) c.push_back({a[i],1});
    for(int i=1;i<=m;i++) c.push_back({b[i],2});
    sort(c.begin()+1,c.begin()+1+n+m,cmp);

    vector<int> p(n+m+1);   //记录前i个中a出现的次数
    for(int i=1;i<=n+m;i++){
        p[i]=p[i-1];
        if(c[i].id==1) p[i]++;
    }

    while(q--){
        int x,y,z;
        cin>>x>>y>>z;
        int cnta=p[z];
        int cntb=z-p[z];
        int ans=0;
        if(cnta<=x&&cntb<=y){
            ans=sa[cnta]+sb[cntb];
        }else if(cnta>x&&cntb<=y){
            ans=sa[x]+sb[z-x];
        }else if(cnta<=x&&cntb>y){
            ans=sa[z-y]+sb[y];
        }
        cout<<ans<<"\n";
    }
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    cin>>_;
    while(_--) solve();
    return 0;
}

二:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); 
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;

const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;



void solve(){
    int n,m,q;
    cin>>n>>m>>q;

    vi a(n+1),b(m+1);
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    sort(a.begin()+1,a.begin()+1+n);
    sort(b.begin()+1,b.begin()+1+m,greater<int>());

    vector<int> c(1);
    for(int i=1;i<=n;i++) c.push_back(a[i]);
    for(int i=1;i<=m;i++) c.push_back(b[i]);

    vi sum(n+m+1,0);    //前缀和
    for(int i=1;i<=n+m;i++) sum[i]=sum[i-1]+c[i];


    while(q--){
        int x,y,z;
        cin>>x>>y>>z;

        auto f=[&](int x)->int{
            return sum[x+z-1]-sum[x-1];
        };

        int l=n-x+1,r=n+y-z+1;
        while(r-l>6){
            int lmid=l+(r-l)/3,rmid=r-(r-l)/3;
            if(f(lmid)>=f(rmid)) r=rmid;
            else l=lmid;
        }
        int ans=0;
        for(int i=l;i<=r;i++){
            ans=max(ans,f(i));
        }
        cout<<ans<<"\n";
    }
}
signed main() {
    vcoistnt
    cout<<fixed<<setprecision(2);
    int _=1;
    cin>>_;
    while(_--) solve();
    return 0;
}
相关推荐
2501_924889552 小时前
商超高峰客流统计误差↓75%!陌讯多模态融合算法在智慧零售的实战解析
大数据·人工智能·算法·计算机视觉·零售
jingfeng5142 小时前
C++模板进阶
java·c++·算法
地平线开发者3 小时前
征程 6X | 常用工具介绍
算法·自动驾驶
地平线开发者3 小时前
理想汽车智驾方案介绍 2|MindVLA 方案详解
算法·自动驾驶
艾莉丝努力练剑4 小时前
【C语言16天强化训练】从基础入门到进阶:Day 7
java·c语言·学习·算法
地平线开发者4 小时前
LLM 中评价指标与训练概要介绍
算法·自动驾驶
Ghost-Face4 小时前
关于并查集
算法
flashlight_hi6 小时前
LeetCode 分类刷题:2529. 正整数和负整数的最大计数
python·算法·leetcode
花火|6 小时前
算法训练营day60 图论⑩ Bellman_ford 队列优化算法、判断负权回路、单源有限最短路
算法·图论
2501_924890526 小时前
商超场景徘徊识别误报率↓79%!陌讯多模态时序融合算法落地优化
java·大数据·人工智能·深度学习·算法·目标检测·计算机视觉