Educational Codeforces Round 147 (Rated for Div. 2) A-C

A.Matching

题意

给你一个由数字和’?'组成的字符串 ?可以替换成0-9 中任何数字,问这个字符串可以匹配多少个数字。

思路

有几个问号就乘以十的几次方,最后减去当字符串第一个为问号的情况,即当第一位为0 其它问号组合的情况,即10的问号总数-1的次方

代码

#include <iostream>
#include <cmath>
using namespace std;
 
void solve();
 
int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}
 
void solve() {
    string a;
    cin>>a;
    int cnt=0;
    if(a[0]=='0'){
        cout<<"0\n";
        return ;
    }
    for (int i = 0; i < a.length(); ++i) {
        if(a[i]=='?') cnt++;
    }
    int ans=pow(10,cnt);
    if(a[0]=='?') ans-=pow(10,cnt-1);
    cout<<ans<<endl;
}

B.Sort the Subarray ## 题意

已知一个数组a,我们可以选择它一个下标范围l,r进行升序排序,得到数组a2。 a=[6,7,3,4,4,6,5], 选定l=2,r=5,那么排序后的a2=[6,3,4,4,7,6,5]。

现给定数组a和a2,求出原来的下标范围l,r。 如果存在多组解,选择下标范围最长的;如果下标范围最长的有多组解,输出任意一解。

思路

分两种情况:

1.a[i]与a2[i]不相同,那这个下标一定在[l,r]范围内

2.a[i]与a2[i]相同,如果在相同的情况下,也在下标范围内,那这个数一定满足升序排列,从左向右看,最左边的相同的数在序列中 看下面a数组的1,即在升序序列中处在正确的位置,那么右边的序列中的数一定都大于这个数,那在一个数相同的情况下,怎么确定在序列中的数是否都大于它呢。

首先先确定一个升序序列,不相同的一定在序列中,如下 2-5 在序列中。

再将序列最左边的数与其左边的数比较,如果比序列中最小的数还小,即意味着这个数在序列中 右边也一样,只是比较是否比最大的数还大。

代码

#include <iostream>
 
using namespace std;
const int N=2*1e5+1;
int a[N];
int b[N];
void solve();
 
int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}
 
void solve() {
   int t;
   cin>>t;
   for (int i = 1; i <= t; ++i)  cin>>a[i];
   for (int i = 1; i <= t; ++i) cin>>b[i];
   int l=1,r=t;
   while(l<=t&&b[l]==a[l]) l++;  
   while(r>0&&a[r]==b[r]) r--; //先确定一个升序序列
   while(l>1&&b[l]>=b[l-1]) l--; //往左边扩 
   while(r<t&&b[r]<=b[r+1]) r++; //往右边扩
   cout<<l<<" "<<r<<endl;
}

C.Tear It Apart

题意

给定一个字符串,操作多次后只剩下同一字符,每次操作消除不相邻的多个字符,求最小操作次数

思路

“abcdef” 每次消除不相邻的多个字符 如这里5个字符 每次消除一半的字符 第一次操作 变为2 第二次 变为1 第三次变为0 多写几个就可以看出 字符数 除以2的t-1次方为1 如5 除以 2的3-1次方 为1 n为字符数 t为操作数
n / 2 t − 1 = 1 n = 2 t − 1 l o g 2 n + 1 = t n/2^{t-1}=1\\ n=2^{t-1}\\ log_2n+1=t n/2t1=1n=2t1log2n+1=t
而最后留下哪一个字符 可以将a到z遍历一遍 看哪个的操作次数最少 而每个字符的操作数取决于最大区间 codeforcesc 要保留c字符 由两个区间 第一个c与第二个c构成一个区间 第二,三个构成一个区间 取决于第一个最大区间长度 注意如果最后一个不是c 在循环后要单独处理这种情况

代码

#include <iostream>
#include<cmath>
using namespace std;
const int N=2*1e5+1;
void solve();

int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}
 
void solve() {
    string s;
    cin >> s;
    int  ans=0x3f; //ans要取最小值 先初始化为最大数
    for (char i = 'a'; i <= 'z'; i++) {
        int l = 0;
        int t = 0;
        for (int j = 0; j < s.length(); ++j) {
            if (s[j] == i) {  //l为区间长度
                t = max(t, (int) log2(l) + 1);
                l = 0;
            } else l++;
        }
        t = max(t, (int) log2(l) + 1); 
        /*单独处理最后一个区间 如上的codeforces*/
        ans = min(ans, t); //取保留任一字符中最小操作数
    }
    cout << ans << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值