zoukankan      html  css  js  c++  java
  • 2017 国庆湖南Day2

    期望得分:100+30+100=230

    实际得分:100+30+70=200

    T3 数组开小了 。。。。。

    记录 1的前缀和,0的后缀和

    枚举第一个1的出现位置

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    #define N 100002
    
    using namespace std;
    
    char s[N];
    
    int num[N];
    
    int suf0[N],pre1[N];
    
    int main()
    {
        freopen("reverse.in","r",stdin);
        freopen("reverse.out","w",stdout);
        scanf("%s",s+1);
        int len=strlen(s+1);
        for(int i=1;i<=len;i++) num[i]=s[i]-'0';
        for(int i=1;i<=len;i++) pre1[i]=pre1[i-1]+num[i];
        for(int i=len;i;i--) suf0[i]=suf0[i+1]+(!num[i]);
        int ans=len;
        for(int i=1;i<=len;i++) ans=min(ans,pre1[i-1]+suf0[i]);
        ans=min(ans,pre1[len]);
        printf("%d",ans);
    }
    View Code

    从1——n枚举一遍

    二进制表示它有哪些数出现过了,相当于哈希

    然后Σ C(i,2)

    #include<cstdio>
    
    using namespace std;
    
    int  f[1026];
    
    void count(int x)
    {
        int s=0;
        while(x)
        {
            s|=1<<x%10;
             x/=10;
        }
        f[s]++;
    }
    
    int main()
    {
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout); 
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) count(i);
        long long ans=0;
        for(int i=1;i<=1023;i++) ans+=1ll*f[i]*(f[i]-1)/2;
        printf("%I64d",ans);
    }
    View Code

    考场思路:

    种类只有2^9种可能

    所以枚举每一种可能

    那问题转化为了 有x种数,用它来组成<=n的数的方案数

    开始想裸的数位DP,但它不能保证所有的x种数都用上

    然后又改的状压DP,dp[i][j] 表示填了i位,使用数的状态为j,

    虽然能保证所有的x种数都用上,但数位DP的作用难以体现:

    若枚举这一位填哪个数,因为不知道前面填了什么,所以也不能确定这一位填什么

    脑补的改进方法是 数位DP加一维表示状态,状压DP加一维表示上一位填了什么

    可行性未知

    考场错误的状压DP

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    int tmp[10],num[10];
    
    int use[10],dp[10][1024];
    int a[10],b[10];
    
    int main()
    {
        int n,len=0;
        scanf("%d",&n); 
        if(n<10) { printf("0"); return 0; }
        while(n) { tmp[++len]=n%10; n/=10;} 
        for(int i=len,len=0;i;i--) num[++len]=tmp[i];
        int tot,sum,T; long long ans=0;
        num[0]=10;
        for(int s=2;s<1023;s++)
        {
            if(s==2)
            {
                int sad=4;
            }
            memset(use,false,sizeof(use)); tot=0;
            memset(b,0,sizeof(b));
            memset(dp,0,sizeof(dp)); 
            for(int i=0;i<10;i++) if(s&(1<<i)) tot++,use[i]=true,b[i]=tot;
            T=1<<tot; 
            for(int i=1;i<=tot;i++) dp[1][1<<i-1]=1;
            for(int i=1;i<len;i++)
                for(int t=T-1;t;t=t&(t-1))
                    for(int j=0;j<=num[i+1];j++) 
                        if(use[j]) dp[i+1][t|1<<b[j]-1]+=dp[i][t];
            tot=0;
            
            for(int i=1;i<=len;i++)  tot+=dp[i][T-1];
            ans+=1ll*tot*(tot-1)/2;
            if(tot) printf("%d %d
    ",s,tot);
        }
        printf("%I64d
    ",ans);
    }
    View Code

    考场错误的数位DP

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    int tmp[10],num[10];
    
    int dp[10][10][10][2];
    bool use[10];
    
    int main()
    {
        int n,len=0;
        scanf("%d",&n); 
        if(n<10) { printf("0"); return 0; }
        while(n) { tmp[++len]=n%10; n/=10;} 
        for(int i=len,len=0;i;i--) num[++len]=i;
        int S=1<<10; long long tot,ans=0;
        for(int s=S-1;s;s=s&(s-1))
        {
            memset(use,false,sizeof(use));
            memset(dp,0,sizeof(dp));
            for(int i=0;i<10;i++) 
              if(s&(1<<i)) use[i]=true;
            for(int i=1;i<10;i++) dp[1][i][0]=1;
            for(int i=1;i<len;i++)
                for(int j=0;j<10;j++)
                    for(int k=0;k<2;k++)
                        if(k)
                            for(int l=0;l<=num[i];l++) dp[i+1][l][1]+=dp[i][j][1];
                        else
                            for(int l=0;l<10;l++)
                                if(l==num[i]) dp[i+1][l][1]+=dp[i][j][0];
                                else dp[i+1][l][0]+=dp[i][j][0];
            tot=0;
            for(int i=1;i<=len;i++) 
                for(int j=0;j<10;j++)
                {
                    tot+=dp[i][j][0]+dp[i][j][1];
                    printf("%d %d
    ",dp[i][j][0],dp[i][j][1]);
                }
                 
            ans+=tot*(tot+1)/2;
        }
        printf("%I64d
    ",ans);
    }
    View Code

    30暴力

    #include<cstdio>
    #include<cstring>
    
    bool visx[10];
    bool visy[10];
    
    using namespace std;
    
    int main()
    {
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout); 
        int n;
        scanf("%d",&n);
        int X,Y,sx,sy,ans=0;
        bool ok;
        for(int x=1;x<n;x++)
        {
            X=x; 
            while(X) 
            {
                if(!visx[X%10]) visx[X%10]=true;
                X/=10;
            }
            for(int y=x+1;y<=n;y++)
            {
                Y=y; 
                while(Y) 
                {
                    if(!visy[Y%10]) visy[Y%10]=true;
                    Y/=10;
                }
                ok=true;
                for(int i=0;i<10 && ok;i++)
                    if(visx[i]!=visy[i]) ok=false;
                ans+=ok;
                memset(visy,0,sizeof(visy));
            }
            memset(visx,0,sizeof(visx));
        }
        printf("%d",ans);
    }
    View Code

    贪心

    肯定是上升的时候,越大越好

    下降的时候,越小越好

    所以有了初步思路:

    每次找连续下降的最后一个,然后找连续上升的最后一个,循环往复

     看似很正确

    但请看下图:

    假设k=2,如果按上面的思路,那么后面会选上9

    接下来要找连续下降 9后面那个点和8都不满足k=2的差值

    所以我们得到的答案=4

    但最优解是不要9,选后面的12和8

    因为9后面的那个点不能下降,所以到了12仍然是处于上升,所以12比9更优

    所以,我们不能找连续的序列,而是

    只要现在处于上升阶段,就找最大的

    只要现在处于下降阶段,就找最小的

    幸亏打了暴力,对拍拍出了这个bug

    #include<algorithm>
    #include<cstdio>
    #include<iostream>
    
    #define N 1000001
    
    using namespace std;
    
    int e[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(); }
    }
    
    int main()
    {
        freopen("wave.in","r",stdin);    
        freopen("wave.out","w",stdout);
        int n,k;
        read(n); read(k);
        for(int i=1;i<=n;i++) read(e[i]);
        bool up=true;
        int now,len=1;
        for(now=1;now<=n && e[now+1]<=e[now];now++);
        int last=e[now++]; 
        while(now<=n)
        {
            if(!up)
            {
                while(now<=n)
                {
                    if(last-e[now]>=k) { last=e[now]; len++; up^=1; break; }
                    else if(e[now]>=last ) last=e[now];
                    now++;
                }
            }
            else
            {
                while(now<=n)
                {
                    if(e[now]-last>=k) { last=e[now]; len++; up^=1; break; }
                    else if(e[now]<=last) last=e[now];
                    now++;
                }
            }
            now++;
        }
        printf("%d",len);
    }
    View Code

    对拍代码(n^2)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    #define N 1000001
    
    using namespace std;
    
    int f[N][2],a[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(); }
    }
    
    int main()
    {
        freopen("data.in","r",stdin);
        freopen("std.out","w",stdout);
        int n,k;
        read(n); read(k);
        for(int i=1;i<=n;++i) read(a[i]);
        int mx,ans=0;
        for(int i=1;i<=n;i++)
        {
            mx=0;
            for(int j=i-1;j;j--) 
                if(a[j]-a[i]>=k) mx=max(mx,f[j][1]);
            f[i][0]=mx+1; ans=max(ans,f[i][0]);
            mx=0;
            for(int j=i-1;j;j--)
                if(a[i]-a[j]>=k) mx=max(mx,f[j][0]);
            if(mx)
            {
                f[i][1]=mx+1; 
                ans=max(ans,f[i][1]);
            }
        }
        printf("%d",ans);
    }
    View Code
  • 相关阅读:
    Android开发总结
    LeakCanary原理分析
    机器学习
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 3. 循环
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 2. 变量
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 1. 神秘朋友
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
    远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7681480.html
Copyright © 2011-2022 走看看