补题链接: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;
}