(寒假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 (树剖) (待补)

题意

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

原文地址:https://www.cnblogs.com/luowentao/p/10351128.html

时间: 2024-10-28 18:03:34

(寒假GYM开黑)2018-2019 ACM-ICPC Brazil Subregional Programming Contest的相关文章

(寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)

layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队博客 C.Coolest Ski Route (记忆化搜索) 题意 给出一个有向图,求出一个权值最长的链, 题解 暴力dfs会超时,所以直接储存每个起点能走到的最远距离 #include<

(寒假GYM开黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

layout: post title: 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! B.Baby Bites (签到模拟) 按照题意模拟就行了 int a[maxn]; string s; int main() { std::ios::syn

Gym.101908 Brazil Subregional Programming Contest(寒假自训第六场)

这几天失眠时间都不太够,室友太会折腾了,感觉有点累,所以昨天的题解也没写,看晚上能不能补起来. B . Marbles 题意:给定N组数(xi,yi),玩家轮流操作,每次玩家可以选择其中一组对其操作,可以把它减去一个数,或同时减去一个数,当玩家操作后出现了(0,0)则胜利. 思路:注意这里是出现(0,0)胜,而不是全都是(0,0)胜,所以我们不能简单的球sg,最后异或得到答案. 但是我们转化一下,如果玩家面对的全是(1,2) 或(2,1),则他胜利,那么我们可以以这两个状态为起点得到sg函数,就

ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Krak&#243;w

ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik's RectangleProblem B: What does the fox say?Problem C: Magical GCDProblem D: SubwayProblem E: EscapeProblem F: DraughtsProblem G: History courseProblem H: C

2019 ACM ICPC 南京站 H. Prince and Princess

题意 王子想要娶公主,但是需要完成一个挑战:在一些房间中找出公主在哪. 每个房间有一个人,他们彼此知道谁在哪个房间.可以问他们三种问题: 你是谁? 在某个房间是谁? 公主在哪个房间? 有三类人,一类一定说真话,一类一定说假话,一类可能说真话可能说假话. 王子知道这三类人的人数分别为 \(a\), \(b\), \(c\),求能否通过问一些问题找到公主在哪,如果能,输出最少需要的问题数. 思路 第三类人有可能说假话,因此最坏情况就是说假话,所以把他们视为第二类人. 首先问所有人第三个问题,那么最坏

The 2019 University of Jordan Collegiate Programming Contest

链接:https://codeforc.es/gym/102267 A. Picky Eater 直接比较 int main(){ int x ,y; scanf("%d %d" ,&x ,&y); if(x>=y){ return printf("1"),0; } else return printf("0"),0; return 0; } B. Primes 素数筛,log判断 int prime[maxn],num_p

The 2019 ACM-ICPC China Shannxi Provincial Programming Contest (西安邀请赛重现) J. And And And

链接:https://nanti.jisuanke.com/t/39277 思路: 一开始看着很像树分治,就用树分治写了下,发现因为异或操作的特殊性,我们是可以优化树分治中的容斥操作的,不合理的情况只有当两点在一条链上才存在,那么直接一遍dfs从根节点向下跑途中维护一下前缀和,把所有情况中不合理情况造成的值修正. 这样的话时间复杂度就可以降得非常低了,感觉还可以优化,但是懒得写了 代码耗时:142ms. 实现代码: #include<bits/stdc++.h> using namespace

(寒假开黑gym)2018 USP Try-outs

layout: post title: (寒假开黑gym)2018 USP Try-outs author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! 许老师! B.Aesthetics in poetry (暴力模拟) #include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=

(寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest

layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! 许老师! Hello SCPC 2018! (签到) #include<bits/stdc++.h> using namespace std; typedef