zoukankan      html  css  js  c++  java
  • [Codeforces #201] Tutorial

    Link:

    传送门

    代码量很少的一套思维题

    A:

    试一试发现最后状态一定是所有$min,max$间$gcd$的倍数

    直接判断数量的奇偶性即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    int n,mx,x,gcd;
    
    int GCD(int x,int y){return !y?x:GCD(y,x%y);}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&x),mx=max(mx,x),gcd=GCD(gcd,x);
        if(!gcd) gcd=1;
        puts((mx/gcd-n)%2?"Alice":"Bob");
        return 0;
    }
    Problem A

    感觉现在自己开始瞎猜结论了……

    看完样例就直接觉得最终状态应该是$[1,max]$……

    猜结论一定要手造数据试一试!

    B:

    $LCS+KMP$

    只要在$dp$状态上多记录一维当前子序列匹配到的位置就能做了

    输出方案的话可以用$map$记录前驱方案各维的值,不过从前向后记忆化搜索可以不用$map$

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    struct Tri{int x,y,z;};
    const int MAXN=105,INF=1<<28;
    map<Tri,Tri> pre;
    char a[MAXN],b[MAXN],c[MAXN],ans[MAXN];
    int la,lb,lc,dp[MAXN][MAXN][MAXN],nxt[MAXN],val[MAXN],tot;
    //重载要写全! 
    bool operator < (const Tri &a,const Tri &b)
    {
        if(a.x==b.x&&a.y==b.y) return a.z<b.z;
        else if(a.x==b.x) return a.y<b.y;
        else return a.x<b.x;
    }
    
    void kmp()
    {
        int k=0;nxt[1]=0;
        for(int i=2;i<=lc;i++)
        {
            while(k&&c[k+1]!=c[i]) k=nxt[k];
            if(c[k+1]==c[i]) k++;nxt[i]=k;
        }
    }
    int cal_nxt(int x,int y)
    {
        while(y&&c[y+1]!=a[x]) y=nxt[y];
        if(c[y+1]==a[x]) y++;
        return y;
    }
    void modify(Tri x,Tri y,int val)
    {
        if(x.x>la||x.y>lb) return;    
        int &t1=dp[x.x][x.y][x.z];
        int &t2=dp[y.x][y.y][y.z];
        if(t1<t2+val)
            t1=t2+val,pre[x]=y;
    }
    //可以不记录pre,从前往后记忆化搜索 
    void print(Tri t)
    {
        int lst=0;
        while(t.x&&t.y)
        {
            if(a[t.x]==b[t.y]) 
                ans[++tot]=a[t.x],val[tot]=dp[t.x][t.y][t.z];        
            t=pre[t];
        }
        while(tot) 
            if(val[tot]!=val[tot+1]) printf("%c",ans[tot--]);
            else tot--;
    }
    int main()
    {
        scanf("%s%s%s",a+1,b+1,c+1);
        la=strlen(a+1);lb=strlen(b+1);lc=strlen(c+1);
        kmp();
        
        for(int i=0;i<=la;i++)
            for(int j=0;j<=lb;j++)
                for(int k=0;k<lc;k++)
                {
                    modify((Tri){i+1,j,k},(Tri){i,j,k},0);
                    modify((Tri){i,j+1,k},(Tri){i,j,k},0);
                    if(a[i+1]!=b[j+1]) continue;
                    int Nxt=cal_nxt(i+1,k);
                    if(Nxt==lc) continue;
                    modify((Tri){i+1,j+1,Nxt},(Tri){i,j,k},1);
                }    
        
        int res=0,t;
        for(int i=0;i<lc;i++)
            if(res<dp[la][lb][i]) res=dp[la][lb][i],t=i;
        if(!res) return puts("0"),0;
        print((Tri){la,lb,t});
        return 0;
    }
    Problem B

    如果$map$里存结构体一定要把小于号重载写全,否则第一维相等就不插入了!

    bool operator < (const Tri &a,const Tri &b)
    {
        if(a.x==b.x&&a.y==b.y) return a.z<b.z;
        else if(a.x==b.x) return a.y<b.y;
        else return a.x<b.x;
    }

    C:

    设$dp[i]$表示从$b+i$到$b$的步数,明显$dp[i]$是单调增的

    这样每次贪心选取最小能达到的$a-amodc[i]$即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10;
    int n,dat[MAXN],a,b,res;
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&dat[i]);
        sort(dat+1,dat+n+1);
        //必须离散化才能保证线性复杂度 
        n=unique(dat+1,dat+n+1)-dat-1;
        scanf("%d%d",&a,&b);
        
        while(a>b)
        {
            int mn=a-1;
            for(int i=1;i<=n;i++)
                if(a-a%dat[i]>=b) mn=min(mn,a-a%dat[i]);
            a=mn;res++;
            while(n&&a-a%dat[n]<b) n--;//一定要优化 
        }
        printf("%d",res);
        return 0;
    }
    Problem C

    注意一定要离散化+去除过大的$c[i]$进行优化!!

    D:

    E:

  • 相关阅读:
    iOS 中UI控件的各种对齐方式总结
    BLE 广播数据解析
    Objective-C中一种消息处理方法performSelector: withObject:
    ios的@property属性和@synthesize属性
    iOS中的字符串扫描类NSScanner
    iOS开发技巧(系列十八:扩展UIColor,支持十六进制颜色设置)
    NSMakeRange基础函数应用
    Objective-C中的占位符,打印BOOL类型数据
    NSUInteger和NSInteger和int
    HDU4870:Rating(DP)
  • 原文地址:https://www.cnblogs.com/newera/p/9773891.html
Copyright © 2011-2022 走看看