Educational Codeforces Round 81 (Rated for Div. 2)

比赛链接:https://codeforces.com/contest/1295

 

A. Display The Number

题意:给n个火柴棍,问能拼出的最大的数是多少。

题解:1需要2根,7需要3根,

优先拼1 ,使位数足够多

但,如果n是奇数(全拿来拼1的话会余一根)且至少有3根,则优先拼一个7作为首位。

代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        scanf("%d",&n);
        if((n&1)&&n>=3) {printf("7");n-=3;}
        for(;n>=2;n-=2) printf("1");
        puts("");
    }
}

 

B. Infinite Prefixes

题意:给定n、x和一个长为n的01串s,s可以无限连接,问有多少个前缀的 cnt0-cnt1==x(cnt0是前缀中0的个数)。前缀包括一个空串,如果答案为无穷个则输出-1。

思路:参考了 https://blog.csdn.net/weixin_45757507/article/details/104112194

我认为T的某个倍数加目前此次遍历过程中0比1多的次数等于x的点就是答案存在的点,翻译成程序就是(x-d)%T==0与此同时我们还要保证此时(x-d)应该和T同号,否则随着子串的延长,会离答案越来越远, 

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
char s[N];
int n,x,a[N];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%s",&n,&x,s+1);
        int ans=0;
        memset(a,0,sizeof a);
        for(int i=1;i<=n;++i) a[i] = a[i-1] + (s[i]=='0'?1:-1) ;
        if(!x) ++ans; //如果x为0,加上空串前缀
        for(int i=1;i<=n;++i){
            if(!a[n] && a[i]==x){ //如果末位为0,且串中有一位等于x,则答案是无穷
                ans=-1;
                break;
            }
            // a[n]*c1+a[i]==x --> (x-a[i])%a[n]==0 // (x-a[i])和a[n]必须同号
            // a[n]*c1-a[i]==x 
            int k=x-a[i];
            if(a[n] && k/a[n]>=0 && k%a[n]==0) ++ans; 
            //若a[n]==0 --> 如果 a[i]==0==x 无穷个答案,上面的情况;如果a[i] == 0 != x,那么a[i]对答案一定无贡献,不用考虑
        }
        printf("%d\n",ans);
    }
}

 

C. Obtain The String

题意:给两个字符串s和t,每次可从s中撷取子序列添到初始为空的字符串z的末尾,问最少要进行多少次这样的操作,z才能变成t?(0<|s|, |t|<=1e5,T<=100)

思路:n^2(二重循环,对着t从s里找)是会T的。

预处理出s各字母的下标,对t的每一位,到s的对应字母中二分查找 比 t的上一位在s中的对应下标 大的下标,如果该字母的所有下标找到头了,就++ans。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
char s[N],t[N];
int main(){
    int T;
    cin>>T;
    while(T--){
        scanf("%s%s",s+1,t+1);
        vector<int>v[26];
        for(int i=1;s[i];++i) v[s[i]-'a'].push_back(i);
        int p=0,ans=1;//初始为1,第一段子序列
        for(int i=1;t[i];++i){
            int tmp=t[i]-'a';
            if(!v[tmp].size()){ans=-1;break;}//不存在该字母
            int pos=upper_bound(v[tmp].begin(),v[tmp].end(),p)-v[tmp].begin();//二分找下标
            if(pos==v[tmp].size()){//没找到(没有更大的位置了)
                ++ans;
                p=v[tmp][0];//从头开始
            }else{
                p=v[tmp][pos];
            }
        }
        printf("%d\n",ans);
    }
}

 

D. Same GCDs

题意:

思路:

代码:

 

E. Permutation Separation

题意:

思路:

代码:

 

F. Good Contest

题意:

思路:

代码:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值