Educational Codeforces Round 82 (Rated for Div. 2)【A、B、C、D】题解(持续更新)

涵盖知识点:贪心、dp、模拟、二进制etc.

比赛链接:

Educational Codeforces Round 82 (Rated for Div. 2)

A:Erasing Zeroes

题意:至少删几个0使得一个0-1串内所有的1都连续。

题解:记录第一个1的位置和最后一个1的位置输出中间0的个数即可

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int t;
 6     cin>>t;
 7     while(t--){
 8         string s;
 9         cin>>s;
10         int st=-1,ed=-1;
11         for(int i=0;i<s.length();i++){
12             if(s[i]=='1'){
13                 ed=i;
14                 if(st==-1){
15                     st=i;
16                 }
17             }
18         }
19         if(st==-1){
20             cout<<0<<"\n";
21             continue;
22         }
23         int res=0;
24         for(int i=st;i<=ed;i++){
25             if(s[i]=='0')
26                 res++;
27         }
28         cout<<res<<"\n";
29     }
30     return 0;
31 }

B:National Project

题意:长度为n的道路,每天可以修的长度为1或选择不修,g天好天气和b天坏天气交替出现,要求至少n/2的路是在好天气下修的,问最少几天修完。

题解:先根据间隔算出遇到n/2天好天气总共需要几天,然后在输出长度和天数的较大值即可(要求路全部修完)。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int main(){
 5     int t;
 6     cin>>t;
 7     while(t--){
 8         ll n,g,b;
 9         ll res=0;
10         cin>>n>>g>>b;
11         ll mid=n/2+n%2;
12         ll gap=mid/g;
13         if(mid%g==0)gap--;
14         res+=gap*g;
15         res+=gap*b;
16         res+=(mid-gap*g);
17         cout<<max(res,n)<<"\n";
18     }
19     return 0;
20 }

C:Perfect Keyboard

题意:求a-z一共26个字母排成一行的序列,要求给定的密码串的所有相邻字母在所求序列中也相邻。

题解:暴力模拟,每添加一个新的字符到序列中时用map记录下标,若序列中已经存在需要新添加的字符时判断是否符合条件,添加字符时判断是否卡死等情况分类讨论。

AC代码:(写的有点丑,可能有更好的写法或者解法)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 map<char,int> mp;
 5 
 6 int main(){
 7     int t;
 8     cin>>t;
 9     while(t--){
10         mp.clear();
11         string s;
12         cin>>s;
13         char res[110];
14         for(int i=0;i<110;i++){
15             res[i]='#';
16         }
17         if(s.length()==1){
18             cout<<"YES\n";
19             for(char i='a';i<='z';i++)
20                 cout<<i;
21             cout<<"\n";
22             continue;
23         }
24         int l=30,r=31;
25         mp[s[0]]=30;
26         mp[s[1]]=31;
27         int idx=31;
28         res[30]=s[0];
29         res[31]=s[1];
30         bool flag=true;
31         for(int i=2;i<s.length();i++){
32             if(s[i]==s[i-2]){
33                 idx=mp[s[i]];
34                 continue;
35             }
36             if(mp[s[i-1]]+1==mp[s[i]]||mp[s[i-1]]-1==mp[s[i]]){
37                 idx=mp[s[i]];
38                 continue;
39             }
40             if(mp[s[i]]!=0){
41                 flag=false;
42                 //cout<<"chongfu\n";
43                // cout<<i<<" ";
44                 //cout<<mp['d']<<" "<<mp['o']<<endl;
45                 break;
46             }
47             if(res[idx+1]=='#'){
48                 res[++idx]=s[i];
49                 mp[s[i]]=idx;
50                 r=idx;
51             }else if(res[idx-1]=='#'){
52                 res[--idx]=s[i];
53                 mp[s[i]]=idx;
54                 l=idx;
55             }else{
56                 flag=false;
57                 //cout<<"kasi\n";
58                 break;
59             }
60         }
61         //cout<<l<<" "<<r<<" ";
62         //for(int i=l;i<=r;i++){
63             //cout<<res[i]<<" ";
64         //}
65         if(flag){
66             cout<<"YES\n";
67             for(int i=l;i<=r;i++){
68                 cout<<res[i];
69             }
70             for(char i='a';i<='z';i++){
71                 if(mp[i]==0)
72                     cout<<i;
73             }
74             cout<<"\n";
75         }else{
76             cout<<"NO\n";
77         }
78     }
79     return 0;
80 }

D:Fill The Bag

题意:给你m个二的倍数,每次操作可以将一个数拆成两半。问你最少几次操作能使n恰好等于其中某些数字的和。

题解:记录m个数的二进制位总和和n的二进制位,若存在相同位对应位数-1,否则将该位向上移动,每两个贡献合并为高一位的一个贡献。若为负数则向高位借用,记录借用的操作数量即为最终答案。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e5+10;
 5 ll cnt[70];
 6 int main(){
 7     int t;
 8     cin>>t;
 9     while(t--){
10         memset(cnt,0,sizeof cnt);
11         ll sum=0,n,m;
12         cin>>n>>m;
13         for(int i=1;i<=m;i++){
14             int x;
15             cin>>x;
16             sum+=x;
17             int p=0;
18             while((x>>p)>1)p++;
19             cnt[p]++;
20         }
21         if(sum<n){
22             cout<<"-1\n";
23             continue;
24         }
25         int idx=0,ans=0;
26         while(n||cnt[idx]<0){
27             cnt[idx]-=(n&1);
28             if(cnt[idx]<0){
29                 cnt[idx+1]--;
30                 ans++;
31             }else{
32                 cnt[idx+1]+=(cnt[idx]>>1);
33             }
34             n>>=1;
35             idx++;
36         }
37         cout<<ans<<"\n";
38     }
39     return 0;
40 }

E:Erase Subsequences

F:Number of Components

G:Sum of Prefix Sums

猜你喜欢

转载自www.cnblogs.com/charles1999/p/12303221.html