Codeforces Round #150 (Div. 2)

A题 Dividing Orange

题目大意:有k个孩子,每个孩子要n个橘子,并且第i个孩子指定要一个橘子编号为ai的橘子,现在你有n*k个橘子,输出满足所有孩子的方案。

题解:模拟,我们先把每个孩子想要的橘子ai给他们,接着把那些还没有分出去的橘子给他们直到他们每个人都拥有n个橘子即可。

View Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
using namespace std;
#define INF 0x73737373
#define EPS 1e-8
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
map <int, int> c;
bool vis[1005];
int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    for(int i = 0; i < k; i++)
    {
        int a;
        scanf("%d", &a);
        c[i] = a;
        vis[a] = true;
    }
    int pos = 1;
    for(int i = 0; i < k; i++)
    {
        printf("%d ", c[i]);
        int num = 0;
        for(;;pos++)
        {
            if(!vis[pos])
            {
                printf("%d ", pos);
                vis[pos] = true;
                num++;
            }
            if(num == n - 1)break;
        }
        printf("\n");
    }
    return 0;
}

B题 Undoubtedly Lucky Numbers

题目大意:定义一种数称为Undoubtedly Lucky Numbers,这种数是最多只由两个不同的数字组成的正整数,给一个上限n输出1-n的范围内有多少个这样的数。

题解:由于这种数最多只由两个不同的数组成,所以我们可以枚举这两个数字的在整个数中的出现位置,dfs即可。

View Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
using namespace std;
#define INF 0x73737373
#define EPS 1e-8
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
set <__int64> ret;
int n, x, y;
void dfs(__int64 num, int times)
{
    if(num > n || times > 10)return;
    ret.insert(num);
    dfs(10 * num + x, times + 1);
    dfs(10 * num + y, times + 1);
}
int main()
{
    scanf("%d", &n);
    for(x = 0; x < 10; x++)
        for(y = x + 1; y < 10; y++)
            dfs(0, 0);
    printf("%d\n", ret.size() - 1);
    return 0;
}

C题 The Brand New Function

题目大意:给一个序列包含n个数,定义f(l, r)为连续区间l、r内所有数求或的结果,输出这个序列一共有多少个结果不同的f(l, r)

题解:因为操作是OR操作,所以,如果f(l, r)和f(l, r-1)的结果相同的话,那么f(x, r-1) 和f(x, r) (1<= x <= l)的结果肯定全部相同。

因此,我们可以枚举这个区间的右值r,然后往左遍历,一旦找到一个l,使得f(l, r) == f(l, r-1)就结束这次遍历,从而用比较少的时间求出所有结果。

View Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
using namespace std;
#define INF 0x73737373
#define EPS 1e-8
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
set <int> ret;
int a[105000];
int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
        ret.insert(a[i]);
        int high = a[i], low = 0;
        for(int j = i - 1; j >= 0; j--)
        {
            high |= a[j];
            low |= a[j];
            ret.insert(high);
            if(high == low)break;
        }
    }
    printf("%d\n", ret.size());
    return 0;
}

D题 Hydra

题目大意:

定义一个九头蛇图,其中两个点u和v分别作为胸部和腹部,胸部会连着h个点作为头,腹部会连着t个点作为尾。

现在有一个无向图,让你确定其子图中是否存在一个九头蛇图。

题解:由于边数和点数都只有10W,所以用邻接表储存后直接暴力即可。

遍历所有点,选出度大于h的点vh作为头(因为要跟腹部相连,所以度应该大于h而不是大于等于h)

接着找跟vh相连并且度大于t的点vt作为腹部,因为一个点不可能又做头又做尾,所以只要检查一下当前的vh和vt是否合法即可。

View Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
using namespace std;
#define INF 0x73737373
#define EPS 1e-8
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
vector <int> edge[105000], head;
bool vis[105000];
int n, m, h, t;
bool solve(int hi, int ti)
{
    int hnum = 0, tnum = 0;
    memset(vis, false, sizeof(vis));
    for(int i = 0; i < edge[hi].size(); i++)
        if(edge[hi][i] != ti)
        {
            hnum++;
            vis[edge[hi][i]] = true;
        }
    for(int i = 0; i < edge[ti].size(); i++)
        if(edge[ti][i] != hi)
            if(!vis[edge[ti][i]]) tnum++;
            else if(hnum > h)
            {
                vis[edge[ti][i]] = false, tnum++, hnum--;
            }
    if(hnum >= h && tnum >= t)
    {
        puts("YES");
        printf("%d %d\n", hi, ti);
        for(int i = 0; i < edge[hi].size() && h; i++)
            if(vis[edge[hi][i]])
            {
                printf("%d ", edge[hi][i]);
                h--;
            }
        puts("");
        for(int i = 0; i < edge[ti].size() && t; i++)
            if(!vis[edge[ti][i]] && edge[ti][i] != hi)
            {
                printf("%d ", edge[ti][i]);
                t--;
            }
        return true;
    }
    return false;
}
bool find()
{
    for(int i = 0; i < head.size(); i++)
        for(int j = 0; j < edge[head[i]].size(); j++)
        {
            int hi = head[i];
            int ti = edge[hi][j];
            if(edge[ti].size() > t)
                if(solve(hi, ti)) return true;
        }
    return false;
}
int main()
{
    scanf("%d%d%d%d", &n, &m, &h, &t);
    for(int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for(int i = 1; i <= n; i++)
        if(edge[i].size() > h) head.push_back(i);
    if(!find())
        puts("NO");
    return 0;
}
 
原文地址:https://www.cnblogs.com/deadblue/p/2796223.html