zoukankan      html  css  js  c++  java
  • 2017北京国庆刷题Day6 morning

    期望得分:100+100+20=220

    实际得分:100+100+20=220

    模拟栈

    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define N 10002
    char s[N],st[N];
    int top;
    int main()
    {
        freopen("kakutani.in","r",stdin);
        freopen("kakutani.out","w",stdout);
        int n,len,lt;
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s",s);
            len=strlen(s);
            top=0;
            for(int i=0;i<len;i++)
                if(s[i]=='4' || s[i]=='7') continue;
                else if(s[i]!='3') st[++top]=s[i];
                else 
                {
                    if(st[top]=='1') top--; 
                    else st[++top]='3';
                }
            if(top) for(int i=1;i<=top;i++) putchar(st[i]);
            else putchar('0');
            printf("
    ");
        }
    }
    View Code

    枚举i为间隔K个录像的左端点,那么间隔录像为[i,i+k-1]

    设第一段为[Sa,Ta],第二段为[Sb,Tb],Ma为min[Sa,Ta],Mb为min[Sb,Tb]

    随着Sa的左移,Ma单调不增

    随着Tb的右移,Mb单调不增

    如果枚举Sa,则有以下式子: Ta-Sa+1+Tb-Sb+1>=B

    即Tb>=B+Sa+Sb-Ta-2

    因为Tb右移,Mb单调不增,所以Tb取等号最优

    所以二分Sa的位置,用st表查询Ma,Mb

    #include<cmath>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define N 1000001
    using namespace std;
    int st[N][21];
    int p,n;
    int logg2[N];
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    void stpre()
    {
        p=log2(n);
        for(int j=1,k=2;j<=p;j++,k<<=1)
            for(int i=1;i+k-1<=n;i++)
                st[i][j]=min(st[i][j-1],st[i+(k>>1)][j-1]);
        for(int i=1;i<=n;i++) logg2[i]=log2(i);
    }
    int getmin(int s,int t)
    {
        p=logg2[t-s+1];
        int len=1<<p;
        return min(st[s][p],st[t-len+1][p]);
    }
    int main()
    {
        freopen("dota.in","r",stdin);
        freopen("dota.out","w",stdout); 
        int A,B,k;
        read(n); read(A); read(B); read(k);
        for(int i=1;i<=n;i++) read(st[i][0]);
        stpre();
        int Sa,Sb,Ta,Tb,Ma,Mb,Mi;
        int ans=0;
        int l,r,mid,tmp;
        for(int i=A+1;i<=n-A-k+1;i++)
        {
            Ta=i-1; Sb=i+k; 
            Tb=max(Sb+A-1,B+i-A+Sb-Ta-2);
            Ma=getmin(i-A,Ta); Mb=getmin(Sb,Tb); 
            l=1; r=i-A; tmp=min(Ma,Mb);
            while(l<=r)
            {
                mid=l+r>>1;
                Tb=max(Sb+A-1,B+mid+Sb-Ta-2);
                Ma=getmin(mid,Ta); Mb=getmin(Sb,Tb);
                tmp=max(tmp,min(Ma,Mb));
                if(Ma<Mb) l=mid+1;                
                else if(Ma==Mb) break;
                else r=mid-1;
            }
            ans=max(ans,tmp);
        }
        printf("%d",ans);
    }
    View Code

    数位DP

    dp[i][j][0/1] 前i位匹配到X的第j位,是否已经包含1个X的数的个数

    二分,计算<=mid的数里的答案

    其中的匹配用kmp

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    LL L,R,K;
    LL dp[19][19][2];
    int len,f[19];
    char X[19];
    int a[19],cnt;
    void kmp()
    {
        len=strlen(X);
        int j;
        for(int i=1;i<len;i++)
        {
            j=f[i];
            while(j && X[i]!=X[j]) j=f[j];
            f[i+1]=X[i]==X[j] ? j+1 : 0;
        }
    }
    LL dfs(int dep,int w,bool lim,bool get)
    {
        if(!dep) return get;
        if(!lim && ~dp[dep][w][get]) return dp[dep][w][get];
        LL res=0;
        int k=lim ? a[dep] : 9;
        int j;
        for(int i=0;i<=k;i++)
        {
            j=w;
            while(j && X[j]-'0'!=i) j=f[j];
            if(X[j]-'0'==i) j++;
            res+=dfs(dep-1,j,lim&&(i==k),get||(j==len));
        }
        return lim ? res : dp[dep][w][get]=res;
    }
    LL query(LL lim)
    {
        int cnt=0;
        while(lim)
        {
            a[++cnt]=lim%10;
            lim/=10;
        }
        memset(dp,-1,sizeof(dp));
        return dfs(cnt,0,true,false);
    }
    int main()
    {
        freopen("spenum.in","r",stdin);
        freopen("spenum.out","w",stdout);
        scanf("%I64d%I64d%s%I64d",&L,&R,X,&K);
        kmp();
        LL tmp=query(L-1);
        if(query(R)<K) { puts("Hey,wake up!"); return 0; }
        LL l=L,r=R,ans,mid;
        while(l<=r)
        {
            mid=l+r>>1;
            if(query(mid)-tmp<K) l=mid+1;
            else ans=mid,r=mid-1;
        }
        printf("%I64d",ans);
    }
    View Code
  • 相关阅读:
    苹果手机页面高度不够会导致下面fixed的按钮看不到了
    IOS系统倒计时直接到结束的问题解决
    TP6集成gatewayworker报错解决
    easywechat实现公众号支付jsapi支付
    Linux 下没有conio.h 的解决方法
    程序跳转语句
    循环控制语句
    arduino入门实践之驱动LCD12864
    Manjaro 安装MariaDB
    Arduino入门实践之人体红外感应模块
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7632014.html
Copyright © 2011-2022 走看看