Codeforces Round #383 (Div. 2)

来源:互联网 发布:剑三毒哥妖孽捏脸数据 编辑:程序博客网 时间:2024/05/17 05:01

A. Arpa’s hard exam and Mehrdad’s naive cheat

找规律即可。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int main(){    int n;    while(scanf("%d", &n) != EOF){        if(n == 0){            printf("1\n");            continue;        }        if(n%4 == 1) printf("8\n");        else if(n%4 == 2) printf("4\n");        else if(n%4 == 3) printf("2\n");        else if(n%4 == 0) printf("6\n");    }    return 0;}

B - Arpa’s obvious problem and Mehrdad’s terrible solution

这道题主要就是利用异或的性质,如果A^B = C,那么C^B = A,那么直接排序二分即可。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1e5+100;#define LL long longint a[maxn];int main(){    int n, x;    while(scanf("%d%d", &n, &x) != EOF){        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);        sort(a+1, a+n+1);        LL ans = 0;        for(int i = 1; i <= n; i++){            int temp = x^a[i];            int l1 = i+1, r1 = n;            while(l1 < r1){                int mid = (l1+r1)/2;                if(a[mid] >= temp) r1 = mid;                else l1 = mid+1;            }            int l2 = i+1, r2 = n;            while(l2 < r2){                int mid = (l2+r2+1)/2;                if(a[mid] <= temp) l2 = mid;                else r2 = mid-1;            } //           printf("l = %d\n", r1); //           printf("r = %d\n", l2);            if(a[r1] == temp && a[l2] == temp)ans += (LL)l2-r1+1;        }        printf("%I64d\n", ans);    }    return 0;}

C - Arpa’s loud Owf and Mehrdad’s evil plan

并查集瞎搞,因为每一个点只可能包含在一个环中,因为每个点的出度为1,因此,如果一个点的度数是奇数那么直接输出-1即可,然后对于奇偶环判断即可,然后找到这些奇偶环中的点数,求最小公倍数即可,但是因为偶数环只用跑一遍就可以了,所以为偶数是要除以2。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 105;#define LL long longint fa[maxn], sum[maxn], degree[maxn];LL gcd(LL a, LL b){    return !b?a:gcd(b, a%b);}int Find(int x){    if(x == fa[x]) return fa[x];    fa[x] = Find(fa[x]);    return fa[x];}void Merge(int from, int to){    int x = Find(from);    int y = Find(to);    if(x != y){        fa[x] = y;        sum[y] += sum[x];    }}void init(){    memset(degree, 0, sizeof(degree));    for(int i = 0; i < maxn; i++) fa[i] = i, sum[i] = 1;}int main(){    int n, to;    while(scanf("%d", &n) != EOF){        init();        for(int from = 1; from <= n; from++){            scanf("%d", &to);            degree[from]++;            degree[to]++;            Merge(from, to);        }        for(int i = 1; i <= n; i++)        if(degree[i]&1){            printf("-1\n");            return 0;        }        LL t = 1;        for(int i = 1; i <= n; i++)            if(fa[i] == i){                if(sum[i]&1) t = t*sum[i]/gcd(t, sum[i]);                else t = t*sum[i]/2/gcd(t, sum[i]/2);            }        printf("%I64d\n", t);    }    return 0;}

D. Arpa’s weak amphitheater and Mehrdad’s valuable Hoses

并查集加分组背包即可,先用并查集跑出所有的组数,每组中需要加上一个物品,该物品就是所有物品的w值和b值之和,然后跑分组背包即可,因为如果加上组数,那么dp数组空间达到了1e9,因此我直接利用了滚动数组进行优化,跑一边可过。

#include <map>#include <set>#include <cstdio>#include <vector>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1050;struct Node{    int w, b;    Node(){}    Node(int _w, int _b):w(_w), b(_b){}};vector <Node> vec[maxn];int w[maxn], b[maxn], fa[maxn];int dp[maxn*maxn];int Find(int x){    if(x == fa[x]) return x;    fa[x] = Find(fa[x]);    return fa[x];}void Merge(int l, int r){    int x = Find(l);    int y = Find(r);    if(x != y) fa[x] = y;}void init(){    for(int i = 0; i < maxn; i++) fa[i] = i, vec[i].clear();}int main(){    int N, M, W;    while(scanf("%d%d%d", &N, &M, &W) != EOF){        init();        for(int i = 1; i <= N; i++) scanf("%d", &w[i]);        for(int i = 1; i <= N; i++) scanf("%d", &b[i]);        int l, r;        for(int i = 0; i < M; i++){            scanf("%d%d", &l, &r);            Merge(l, r);        }        int cnt = 0;        map <int, int> Map;        for(int i = 1; i <= N; i++){            if(Map[Find(i)]) vec[Map[Find(i)]].push_back(Node(w[i], b[i]));            else{                Map[Find(i)] = ++cnt;                vec[cnt].push_back(Node(w[i], b[i]));            }        }        for(int i = 1; i <= cnt; i++){            int xx = 0, yy = 0;            for(int j = 0; j < vec[i].size(); j++){                xx += vec[i][j].w;                yy += vec[i][j].b;            }            vec[i].push_back(Node(xx, yy));  //          printf("xx = %d, yy = %d\n", xx, yy);        }        memset(dp, 0, sizeof(dp));        for(int i = 1; i <= cnt; i++)            for(int j = W; j >= 0; j--)                for(int k = 0; k < vec[i].size(); k++)                    if(j >= vec[i][k].w) dp[j] = max(dp[j], dp[j-vec[i][k].w] + vec[i][k].b);        printf("%d\n", dp[W]);    }    return 0;}

E. Arpa’s overnight party and Mehrdad’s silent entering

想通了这道题,这道题构造的地方就是2*i-1和2*i连边,首先这样保证了任意三个相邻的不可能有同一种食物,那么这种构造为什么对呢,首先这样处理之后可以保证每个点的入度等于出度等于2,如果相邻2个点正好是男女朋友,那么这样处理之后一定还是二分图,如果不是,因为每个点入度出度都为2,因此每个点必定是环里的一点,又因为环中的边一定是男女朋友边和相邻边交替进行的,所以一定有偶数条,那么这样一来还是二分图,所以证明成立。然后直接黑白染色即可。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 2e5+100;struct Edge{    int to, next;}e[maxn<<2];int head[maxn], color[maxn], l[maxn], r[maxn], tot;void addedge(int from, int to){    e[tot].to = to;    e[tot].next = head[from];    head[from] = tot++;}void dfs(int u, int c){    color[u] = c;    for(int i = head[u]; i != -1; i = e[i].next){        int v = e[i].to;        if(color[v] == -1) dfs(v, 1-c);    }}void init(){    memset(head, -1, sizeof(head));    memset(color, -1, sizeof(color));    tot = 0;}int main(){    int n;    while(scanf("%d", &n) != EOF){        init();        for(int i = 1; i <= n; i++){            scanf("%d%d", &l[i], &r[i]);            addedge(l[i], r[i]);            addedge(r[i], l[i]);            addedge(2*i-1 , 2*i);            addedge(2*i, 2*i-1);        }        for(int i = 1; i <= 2*n; i++)            if(color[i] == -1) dfs(i, 0);        for(int i = 1; i <= n; i++)            printf("%d %d\n", color[l[i]]+1, color[r[i]]+1);    }    return 0;}
1 0
原创粉丝点击