zoukankan      html  css  js  c++  java
  • Codeforces Training S03E01泛做

    http://codeforces.com/gym/101078

    和ysy、方老师一起打的virtual

    image

    打的不是很好...下面按过题顺序放一下过的题的题(dai)解(ma)。

    A

    给两个1~n的排列,把它们割成尽量短的一些段,使得每一段sort之后一样。

    随便写个hash了事(1min交是因为之前顺手写了这题)

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #ifdef LOCAL
    #define TIMER cerr<<clock()<<"ms
    "
    #else
    #define TIMER
    #endif
    #define SZ 666666
    int n,a[SZ],b[SZ];
    int main()
    {
        int T; scanf("%d",&T);
        while(T--)
        {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        for(int i=1;i<=n;i++) scanf("%d",b+i);
        int ca1=0,ca2=0,ca3=1,cb1=0,cb2=0,cb3=1;
        int lst=0;
        for(int i=1;i<=n;i++)
        {
            ca1+=a[i]; cb1+=b[i];
            ca2^=a[i]; cb2^=b[i];
            ca3*=a[i]+(233^n)+666; cb3*=b[i]+(233^n)+666;
            if(ca1!=cb1||ca2!=cb2||ca3!=cb3);else
            {
                printf("%d-%d ",lst+1,i); lst=i;
                ca1=0,ca2=0,ca3=1,cb1=0,cb2=0,cb3=1;
            }
        }
        puts("");
        }
    }

    D

    有一排洞,从1开始左到右编号,对于每个m,如果m是偶数,那么m和m/2有一条绳子相连,如果m是奇数,m与3m+1有一条绳子相连。

    现在在n和n+1这两个洞中间劈一刀,问会砍断多少条绳子。

    推推公式...ysy写的

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    int t,n;
    inline int s(int l,int r)
    {
        if(!(l&1))
          l++;
        if(!(r&1))
          r--;
        return (r-l)/2+1;
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
          {
           scanf("%d",&n);
           printf("%d
    ",n-n/2+s((n-1)/3+1,n));
          }
        return 0;
    }

    L

    有一个01串,现在要通过交换变成前面全是0,后面全是1。

    交换i、j,i<=j需要sqrt(j-i)的代价,求最小代价。

    注意到(目测出)sqrt(a+b+c)+sqrt(b)<sqrt(a+b)+sqrt(b+c)(因为sqrt增长越来越慢),那么我们只要倒着暴力枚举,能换就换。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #ifdef LOCAL
    #define TIMER cerr<<clock()<<"ms
    "
    #else
    #define TIMER
    #endif
    #define SZ 666666
    char s[SZ];
    char ep[SZ];
    int n;
    int main()
    {
        scanf("%s",s);
        n=strlen(s);
        int zero=0;
        for(int i=0;i<n;i++) zero+=s[i]=='0';
        for(int i=0;i<n;i++) ep[i]=(i>=zero)+48;
        double ans=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]==ep[i]) continue;
            for(int j=n-1;j>=i+1;j--) 
            {
                if(s[j]!=ep[i]) continue;
                swap(s[i],s[j]);
                ans+=sqrt(j-i);
                break;
            }
        }
        printf("%.11lf
    ",ans);
    }

    C

    有一个3*3*n的立方体,每一块可以和相邻块匹配,求全部匹配上的方案数。

    十分难写的状压dp,ysy码的

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    int t,n,f[5010][600],g[600][600],a[600][600],x[10][10],q=10007;
    inline int dfs(int i,int j)
    {
        if(i>3)
          return 1;
        if(j>3)
          return dfs(i+1,1);
        if(!x[i][j])
          return dfs(i,j+1);
        int p=0;
        if(x[i][j+1])
          {
           x[i][j]=0;
           x[i][j+1]=0;
           p+=dfs(i,j+1);
           x[i][j]=1;
           x[i][j+1]=1;
          }
        if(x[i+1][j])
          {
           x[i][j]=0;
           x[i+1][j]=0;
           p+=dfs(i,j+1);
           x[i][j]=1;
           x[i+1][j]=1;
          }
        return p;
    }
    inline void js(int n,int m)
    {
        int i,j;
        for(i=0;i<9;i++)
          if((n&(1<<i)) && (m&(1<<i)))
            return;
          else if((n&(1<<i)) || (m&(1<<i)))
            x[i/3+1][i%3+1]=0;
          else
            x[i/3+1][i%3+1]=1;
        g[n][m]=dfs(1,1);
        a[n][++a[n][0]]=m;
    }
    int main()
    {
        int i,j,k;
        n=5000;
        for(i=0;i<512;i++)
          for(j=0;j<512;j++)
            js(i,j);
        f[0][0]=1;
        for(i=1;i<=n;i++)
          for(j=0;j<512;j++)
            for(k=1;k<=a[j][0];k++)
              f[i][a[j][k]]=(f[i][a[j][k]]+f[i-1][j]*g[j][a[j][k]])%q;
        scanf("%d",&t);
        while(t--)
          {
           scanf("%d",&n);
           printf("%d
    ",f[n][0]);
          }
        return 0;
    }

    F

    交互库走迷宫,最后输出最短路径。

    一波dfs即可,注意细节。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #ifdef LOCAL
    #define TIMER cerr<<clock()<<"ms
    "
    #else
    #define TIMER
    #endif
    #define SZ 666666
    int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
    int npp[233];
    bool mp[233][233][5];
    int ex=-1,ey=-1;
    bool vis[233][233];
    char tmp[2333],fm[]={"NSEW"};
    #define P 101
    bool& Vis(int a,int b)
    {
        return vis[a+P][b+P];
    }
    bool* Mp(int a,int b)
    {
        return mp[a+P][b+P];
    }
    #define FFF fflush(NULL);
    void dfs(int x,int y)
    {
        Vis(x,y)=1;
        scanf("%s",tmp);
        for(int i=0;tmp[i];i++)
        {
            if(tmp[i]=='*')
            {
                ex=x; ey=y;
            }
            else Mp(x,y)[npp[tmp[i]]]=1;
        }
        for(int i=0;i<4;i++)
        {
            if(!Mp(x,y)[i]) continue;
            if(Vis(x+dx[i],y+dy[i])) continue;
            printf("%c
    ",fm[i]); FFF
            dfs(x+dx[i],y+dy[i]);
            printf("%c
    ",fm[i^1]); FFF
            scanf("%s",tmp);
        }
    }
    pii ps[SZ];
    int dis[233][233];
    int& Dis(int a,int b)
    {
        return dis[a+P][b+P];
    }
    void bfs()
    {
        memset(dis,127/3,sizeof(dis));
        int inf=dis[0][0];
        int h=0,t=0;
        Dis(0,0)=0; ps[t++]=pii(0,0);
        while(h^t)
        {
            pii x=ps[h++];
            for(int k=0;k<4;k++)
            {
                if(!Mp(x.fi,x.se)[k]) continue;
                if(Dis(x.fi+dx[k],x.se+dy[k])!=inf) continue;
                Dis(x.fi+dx[k],x.se+dy[k])=Dis(x.fi,x.se)+1;
                ps[t++]=pii(x.fi+dx[k],x.se+dy[k]);
            }
        }
    }
    int T;
    int main()
    {
        npp['N']=0; npp['S']=1; npp['E']=2; npp['W']=3;
        scanf("%d",&T);
        while(T--)
        {
            ex=-2333, ey=-2333;
            memset(mp,0,sizeof(mp));
            memset(vis,0,sizeof(vis));
            dfs(0,0);
            if(ex==-2333)
            {
                puts("-1"); FFF
                continue;
            }
            memset(vis,0,sizeof(vis));
            bfs();
            printf("%d
    ",Dis(ex,ey)); FFF
        }
    }

    I

    叫你写一个编辑器,可以指针左移,指针右移,打一个字母。

    写个链表,方老师写的。

    # include <stdio.h>
    # include <string.h>
    using namespace std;
    
    int test;
    char str[1300000];
    
    int pre[1300000], nxt[1300000], s[1300000], cur=0, siz=0, sz=0;
    
    
    int main() {
        scanf("%d", &test);
        while(test--) {
            for (int i=0; i<=1000000; ++i) pre[i]=nxt[i]=s[i]=0;
            cur=0,siz=0,sz=0;
            scanf("%s", str);
            sz=strlen(str);
            for (int i=0; i<sz; ++i) {
                if(str[i] == '<') {
                    if(cur != 0) cur = pre[cur];
                }
                else if(str[i] == '>') {
                    if(nxt[cur] != 0) cur = nxt[cur];
                } else if(str[i] == '-') {
                    if(cur) {
                        nxt[pre[cur]] = nxt[cur];
                        pre[nxt[cur]] = pre[cur];
                        cur = pre[cur];
                    }
                } else {
                    ++siz;
                    nxt[siz] = nxt[cur];
                    pre[siz] = cur;
                    nxt[cur] = siz;
                    int NEXT = nxt[siz];
                    pre[NEXT] = siz;
                    s[siz] = str[i];
                    cur=siz;
                }
            }
            int pos = nxt[0];
            while(pos != 0) {
                printf("%c", (char)s[pos]);
                pos=nxt[pos];
            }
            puts("");
        }
    }

    E

    w*h的矩形内有c个圆,给定圆心半径,圆两两不相交(可能相离、相切),求矩形内一个最大的圆使得与任何给定圆不交,输出半径,相对/绝对误差1e-6。

    瞎退火,似乎调参挺蛋疼的,ysy写的。

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    int t,a,b,n,x[51],y[51],r[51];
    double sx,sy,sr,tx[1000],ty[1000],tr[1000],p;
    int main()
    {
        srand(time(NULL));
        int i,j,l;
        double k,q;
        scanf("%d",&t);
        while(t--)
          {
           scanf("%d%d%d",&a,&b,&n);
           for(i=1;i<=n;i++)
             scanf("%d%d%d",&x[i],&y[i],&r[i]);
           p=0;
           for(i=1;i<=10;i++)
             {
              sx=double(((rand()<<15)+rand())%(10*a+1))/10;
              sy=double(((rand()<<15)+rand())%(10*b+1))/10;
              sr=min(min(sx,a-sx),min(sy,b-sy));
              for(j=1;j<=n;j++)
                sr=min(sr,sqrt((sx-x[j])*(sx-x[j])+(sy-y[j])*(sy-y[j]))-r[j]);
              for(k=1e6;k>1e-9;k*=0.9)
                {
                 for(l=1;l<=10;l++)
                   {
                    q=double(((rand()<<15)+rand())%6283)/1000;
                    tx[l]=sx+k*sin(q);
                    ty[l]=sy+k*cos(q);
                    tx[l]=min(max(tx[l],0.0),double(a));
                    ty[l]=min(max(ty[l],0.0),double(b));
                    tr[l]=min(min(tx[l],a-tx[l]),min(ty[l],b-ty[l]));
                    for(j=1;j<=n;j++)
                      tr[l]=min(tr[l],sqrt((tx[l]-x[j])*(tx[l]-x[j])+(ty[l]-y[j])*(ty[l]-y[j]))-r[j]);
                   }
                 for(l=1;l<=10;l++)
                   if(tr[l]>sr)
                     {
                      sx=tx[l];
                      sy=ty[l];
                      sr=tr[l];
                     }
                }
              p=max(p,sr);
             }
           printf("%.9lf
    ",p);
          }
        return 0;
    }

    J

    给出一个填字游戏,有横着的和竖着的,横着的互相不交,竖着的互相不交,现在填上去发现横竖有一些交叉的地方不一样,不能共存。于是让你求出最多的可以共存的。

    把不能共存的连边,就是要求二分图最大独立集。n-最大匹配即可。

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <string.h>
    #include <vector>
    #include <limits>
    #include <set>
    #include <map>
    using namespace std;
    namespace gg
    {
    #define SZ 666666
    int n,M=1;typedef long long ll;
    int fst[SZ],nxt[SZ],vb[SZ],cap[SZ];
    void _ad_dl(int a,int b,int c) {++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;cap[M]=c;}
    void ad_dl(int a,int b,int c) {_ad_dl(a,b,c); _ad_dl(b,a,0);}
    int S,T,q[SZ],d[SZ];
    bool bfs()
    {
        for(int i=1;i<=n+1;i++) d[i]=-1;
        d[S]=0; q[1]=S; int h=1,t=2;
        while(h!=t)
        {
            int cur=q[h++];
            for(int e=fst[cur];e;e=nxt[e])
            {
                int b=vb[e];
                if(d[b]==-1&&cap[e]) d[b]=d[cur]+1, q[t++]=b;
            }
        }
        return d[T]!=-1;
    }
    int dfs(int x,int f)
    {
        if(f<=0) return 0;
        if(x==T) return f;
        int ca=0;
        for(int e=fst[x];e;e=nxt[e])
        {
            int b=vb[e];
            if(d[b]!=d[x]+1) continue;
            int w=dfs(b,min(cap[e],f-ca));
            cap[e]-=w; cap[e^1]+=w; ca+=w;
            if(ca==f) break;
        }
        if(!ca) d[x]=-1;
        return ca;
    }
    #define inf 1000000000
    int dinic()
    {
        int ans=0;
        while(bfs()) ans+=dfs(S,inf);
        return ans;
    }
    int Tat,h,v,x1[SZ],y1[SZ],x2[SZ],y2[SZ];
    int s1l[SZ],s2l[SZ];
    char s1[503][1003],s2[503][1003];
    int main()
    {
        //freopen("test.txt","r",stdin);
        scanf("%d",&Tat);
        while(Tat--)
        {
            M=1;
            scanf("%d%d",&h,&v);
            for(int i=1;i<=h;i++)
            {
                scanf("%d%d ",x1+i,y1+i);
                gets(s1[i]);
                s1l[i]=strlen(s1[i]);
            }
            for(int i=1;i<=v;i++)
            {
                scanf("%d%d ",x2+i,y2+i);
                gets(s2[i]);
                s2l[i]=strlen(s2[i]);
            }
            n=h+v; S=++n; T=++n;
            for(int i=1;i<=n;i++) fst[i]=0;
            for(int i=1;i<=h;i++) ad_dl(S,i,1);
            for(int i=1;i<=v;i++) ad_dl(i+h,T,1);
            for(int i=1;i<=h;i++)
            {
                for(int j=1;j<=v;j++)
                {
                    int xx=x2[j],yy=y1[i];
                    bool ok=1;
                    if(x1[i]<=xx&&xx<=x1[i]+s1l[i]-1)
                    {
                    if(y2[j]<=yy&&yy<=y2[j]+s2l[j]-1)
                    {
                        if(s1[i][xx-x1[i]]==s2[j][yy-y2[j]])
                        ok=1;
                        else ok=0;
                    }
                    }
                    //cout<<i<<","<<j<<" "<<ok<<"
    ";
                    if(!ok) ad_dl(i,j+h,1);
                }
            }
            printf("%d
    ",h+v-dinic());
        }
    }
    }
    int main()
    {
        gg::main();
    }

    接下来就卡题了...打出gg

  • 相关阅读:
    【Win 10 应用开发】在后台播放视频
    【Win 10 应用开发】UI Composition 札记(八):用 XamlLight 制作灯光效果
    【Win 10 应用开发】UI Composition 札记(七):基于表达式的动画
    【Win 10 应用开发】UI Composition 札记(六):动画
    Redis中的Scan命令的使用
    MySQL8.0新特性
    IP白名单的实现(PHP)
    mysql分组后获取每个组排序后的第一条数据(整行)
    PHP 之sha256 sha512封装
    Mysql数据库中CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP区别
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/5859170.html
Copyright © 2011-2022 走看看