zoukankan      html  css  js  c++  java
  • (寒假GYM开黑)2018-2019 ACM-ICPC Brazil Subregional Programming Contest


    layout: post
    title: 2018-2019 ACM-ICPC Brazil Subregional Programming Contest
    author: "luowentaoaa"
    catalog: true
    tags:
    mathjax: true
    - codeforces


    传送门

    付队!

    许老师!

    B.Marbles (nim博弈)

    题意

    一个棋盘n个点,每次可以把一个棋子移动到(x-d,y) or (x,y-d) or (x-d,y-d) 把其中一个棋子移动到(0,0)的人就胜利

    问先手能否必胜

    思路

    我非常喜欢的一题,一开始看到题面第一反应我操nim博弈煞笔题,然后傻逼一样得写了 判断到全部到(0,0)就赢的博弈,后面发现我想错了,我写的是相当于把全部石子取完的博弈,而这题只要把其中一堆石子取完就赢了,所以不正确,还是许老师厉害,把题意转换一下,题目开始是到(0,0)就赢,那什么情况下肯定输呢,那就是到(1,2) (2,1)这种死局的情况,每个人肯定都不想发生这种情况,于是我们就把题目转化成 把石子取到(1,2) (2,1)这种奇异态,而如果一个人面临这种局面那就是稳输的,于是我们把(1,2)这种状态构造成取完,而后面一个人面临一个取完(只有必败态的)时候那他就必输,所以这题就变成把N堆石子取成必输态的NIM博弈了,注意要特判先手直接赢的情况

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    int sg[110][110];
    int flag[500];
    void init(){
        for(int i=1;i<=100;i++)sg[i][0]=sg[0][i]=sg[i][i]=0;
        for(int i=1;i<=100;i++){
            for(int j=1;j<=100;j++){
                if(i==j)continue;
                memset(flag,0,sizeof(flag));
                for(int k=1;k<i;k++)if(k!=j)flag[sg[k][j]]=1;
                for(int k=1;k<j;k++)if(k!=i)flag[sg[i][k]]=1;
                for(int k=1;k<min(i,j);k++)
                    if(i-k!=j-k)flag[sg[i-k][j-k]]=1;
                for(int k=0;k<500;k++){
                    if(flag[k]==0){sg[i][j]=k;break;}
                }
            }
        }
    }
    
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int n;
        cin>>n;
        init();
        int f=0;
        int ans=0;
        while(n--){
            int a,b;
            cin>>a>>b;
            ans^=sg[a][b];
            if(a==b)f=1;
        }
        if(f||ans)cout<<"Y"<<endl;
        else cout<<"N"<<endl;
        return 0;
    }
    

    D.Unraveling Monty Hall(水题)

    判断不是1的个数就行,大早上读题读得我怀疑人生

        int n;
        cin>>n;
        int ans=0;
        while(n--){
            int a;cin>>a;ans+=(a==1)?0:1;
        }
        cout<<ans<<endl;
        return 0;
    }
    

    E.Enigma (模拟)

    题意

    给你两个字符串s,t让判断前strlen(t)中的s有多少个是T中没有的

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e2+50;
    const ll inf=1e10;
    const double eps=1e-5;
    
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        string s;
        string t;
        cin>>s>>t;int ans=0;
        int len=s.size();int len1=t.size();
        for(int i=0;i<len-len1+1;i++){
            bool flag=1;
            for(int j=0;j<len1;j++)if(t[j]==s[i+j])flag=0;
            ans+=flag;
        }
        cout<<ans<<endl;
        return 0;
    }
    
    

    F.Music Festival (线段树/线段数组) (待补)

    题意

    有N个舞台(N<10),第i个舞台有Mi首歌(M总和<1000),给出每首歌的起始时间s,和终止时间t,以及价值val; 我们听完一首歌可以任意瞬移到另外的舞台,即不考虑时间边界。现在让你选择一种方案,使得每个舞台都至少听了一首歌,求最大价值。

    题解

    G.Gasoline (二分网络流)

    题意

    有p个加油站,r个油田,给出每个加油站需要的油以及每个油田库存的油,有C条加油站到油田的带权路,求每个加油站都能加满油时的最长的运输时间的最小值。

    题解

    二分最小值,建图,套网络流模板完事

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e5+50;
    const ll inf=1e10;
    const ll INF = 1000000000;
    const double eps=1e-5;
    struct Edge {
      int from, to;
      ll cap, flow;
    };
    
    struct Dinic {
      int n, m, s, t;
      vector<Edge> edges;    // 边数的两倍
      vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
      bool vis[maxn];         // BFS使用
      int d[maxn];           // 从起点到i的距离
      int cur[maxn];        // 当前弧指针
    
      void ClearAll(int n) {
        for(int i = 0; i < n; i++) G[i].clear();
        edges.clear();
      }
    
      void ClearFlow() {
        for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
      }
    
      void AddEdge(int from, int to, ll cap) {
        edges.push_back((Edge){from, to, cap, 0});
        edges.push_back((Edge){to, from, 0, 0});
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
      }
    
      bool BFS() {
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s);
        vis[s] = 1;
        d[s] = 0;
        while(!Q.empty()) {
          int x = Q.front(); Q.pop();
          for(int i = 0; i < G[x].size(); i++) {
            Edge& e = edges[G[x][i]];
            if(!vis[e.to] && e.cap > e.flow) {
              vis[e.to] = 1;
              d[e.to] = d[x] + 1;
              Q.push(e.to);
            }
          }
        }
        return vis[t];
      }
    
      int DFS(int x, ll a) {
        if(x == t || a == 0) return a;
        int flow = 0, f;
        for(int& i = cur[x]; i < G[x].size(); i++) {
          Edge& e = edges[G[x][i]];
          if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
            e.flow += f;
            edges[G[x][i]^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0) break;
          }
        }
        return flow;
      }
    
      ll Maxflow(int s, int t) {
        this->s = s; this->t = t;
        int flow = 0;
        while(BFS()) {
          memset(cur, 0, sizeof(cur));
          flow += DFS(s, INF);
        }
        return flow;
      }
    
      vector<int> Mincut() { // call this after maxflow
        vector<int> ans;
        for(int i = 0; i < edges.size(); i++) {
          Edge& e = edges[i];
          if(vis[e.from] && !vis[e.to] && e.cap > 0) ans.push_back(i);
        }
        return ans;
      }
    
      void Reduce() {
        for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
      }
    };
    
    Dinic g;
    
    int a[maxn],b[maxn],u[maxn],v[maxn],w[maxn];
    int p,r,c,sum=0;
    int S,T;
    bool isok(int x){
        g.ClearAll(T+1);
        for(int i=1;i<=p;i++)g.AddEdge(S,i,a[i]);
        for(int i=1;i<=r;i++)g.AddEdge(p+i,T,b[i]);
        for(int i=1;i<=c;i++)if(w[i]<=x)g.AddEdge(u[i],p+v[i],inf);
        ll res=g.Maxflow(S,T);
        if(res==sum)return true;
        else return false;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
    
        cin>>p>>r>>c;
        S=0,T=p+r+1;
        for(int i=1;i<=p;i++)cin>>a[i],sum+=a[i];
        for(int i=1;i<=r;i++)cin>>b[i];
        for(int i=1;i<=c;i++)cin>>u[i]>>v[i]>>w[i];
        int L=0,R=1e7,ans=-1;
        while(L<=R){
            int mid=(L+R)/2;
            if(isok(mid))R=mid-1,ans=mid;
            else L=mid+1;
        }
        if(ans==-1)cout<<-1<<endl;
        else cout<<ans<<endl;
        return 0;
    }
    

    I.Switches (模拟)

    题意

    给定N个灯,以及开始状态。M个开关集合,每次使用一个开关,这个集合的状态会改变。 现在一次按1到M个开关,即1,2,3,...M ,1, 2,... 问第几次会全部关掉。

    思路

    直接模拟咯,用bitset表示灯的状态

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e5+50;
    const ll inf=1e10;
    const ll INF = 1000000000;
    const double eps=1e-5;
    bitset<1010>b[1100],c;
    
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int n,m,k,x;
        cin>>n>>m>>k;
        for(int i=0;i<k;i++)cin>>x,c.set(x);
        for(int i=1;i<=n;i++){
            cin>>k;while(k--)cin>>x,b[i].set(x);
        }
        for(int i=1;i<=n;i++){
            c^=b[i];
            if(c.count()==0){
                cout<<i<<endl;return 0;
            }
        }
        for(int i=1;i<=n;i++){
            c^=b[i];
            if(c.count()==0){
                cout<<i+n<<endl;
                return 0;
            }
        }
        cout<<-1<<endl;
        return 0;
    }
    
    

    L.Subway Lines (树剖) (待补)

    题意

    给一棵树,询问两条路径上公共点的个数。

  • 相关阅读:
    【最大流之EdmondsKarp算法】【HDU1532】模板题
    【矩阵乘法经典应用】【ZOJ3497】【Mistwa】
    【矩阵专题】
    【斐波拉契+数论+同余】【ZOJ3707】Calculate Prime S
    对拍BAT
    【枚举+贪心】【ZOJ3715】【Kindergarten Electiond】
    计算(a/b)%c
    斐波拉契数列性质
    【类克鲁斯卡尔做法+枚举最小边】【HDU1598】【find the most comfortable road】
    【并查集+拓扑排序】【HDU1811】【Rank of Tetris】
  • 原文地址:https://www.cnblogs.com/luowentao/p/10351128.html
Copyright © 2011-2022 走看看