Codeforces Round #177 (Div. 2)

A: 求个和就行。

B:

题意:

给定一个n*m的矩阵,将每个方格内都有一个值。我们可以选择其中的任意一个方格执行+d 或者-d操作,问最终使得方格内的数全部相同的最小不数。

思路:

贪心,中位数

找最小值以及最大值,然后从最小值不断+d操作记录可能出现的数,知道大于最大值。然后查看一下所有矩阵中的数是否全部出现,如果全部出现,则说明一定可以得到一个所有值相同的矩阵。然后我们将所有值排序,取中位数,则中位数就是我们要得到的相等的那个值,然后计算每一个小方格到达该值的步数即可。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 107
#define N 107
using namespace std;

const int inf = 0x7f7f7f7f;

int a[N*N],la;
bool vt[N*N];

int main()
{
//    Read();
    int n,m,d;
    int i,j;
    scanf("%d%d%d",&n,&m,&d);
    la = 0; CL(vt,false);

    int mi = inf;
    int ma = 0;
    for (i = 0; i < n; ++i)
    {
        for (j = 0; j < m; ++j)
        {
            scanf("%d",&a[la]);
            mi = min(a[la],mi);
            ma = max(a[la],ma);
            la++;
        }
    }
    i = mi;
    while (i <= ma)
    {
        vt[i] = true;
        i += d;
    }
    bool flag = false;
    for (i = 0; i < la; ++i)
    {
        if (!vt[a[i]])
        {
            flag = true;
            break;
        }
    }
    if (flag) printf("-1\n");
    else
    {
        sort(a,a + la);
//        for (i = 0; i < la; ++i) printf(">>%d\n",a[i]);
        int pos = 0;
        if (la%2 == 1) pos = la/2;
        else  pos = la/2 - 1;
        int tmp = a[pos];
//        printf("%d %d\n",pos,tmp);
        int ans = 0;
        for (i = 0; i < la; ++i)
        {
            ans += abs(a[i] - tmp)/d;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

C:

题意:

给你一个长度为n的字符串,这些字符串由小写英文字母组成,要求长度为n的字符串里面必须包含有k个不通过的英文字母并且相邻两个字符不能相同,求满足上述条件的字典序最下的字符

串。

思路:
贪心:

见代码:

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 107
#define N 1000007
using namespace std;

const int inf = 0x7f7f7f7f;
char s[N];

int main()
{
//    Read();
    int n,m;
    int i,j;
    while (~scanf("%d%d",&n,&m))
    {

        if (m > n) printf("-1\n");//m > n 肯定不行
        else if (n == m)//相等
        {
            for (i = 0; i < n; ++i) printf("%c",'a' + i);
            printf("\n");
        }
        else// n > m
        {
            if (m == 1)//m == 1是不存在的
            {
                printf("-1\n");
            }
            else if (m == 2)// m == 2  ab是最小的
            {
                int f = 0;
                for (i = 1; i <= n; ++i)
                {
                    if (f == 0)
                    {
                        printf("a");
                        f = 1;
                    }
                    else
                    {
                        printf("b");
                        f = 0;
                    }
                }
                printf("\n");

            }
            else
            {
                int f = 0;
                for (i = 1; i <= n - (m - 2); ++i)//前一部分是ab
                {
                    if (f == 0)
                    {
                        printf("a");
                        f = 1;
                    }
                    else
                    {
                        printf("b");
                        f = 0;
                    }
                }
                //后一部分是不同的其他字符
                for (i = 0; i < m - 2; ++i) printf("%c",'a' + i + 2);

                printf("\n");
            }
        }
    }
    return 0;
}

 

D:

题意:

给定两个数n,k,有n个房间,每个房间都一个以牌匾,上边标着下一个房间的房间号,房间号1-n。问满足:

1:从1 - k任意一件房间出发都能达到1的;

2:从k + 1 到 n 任意一间房间出发都不能到达1;

3:从1出发一定能够经过大于0的步数到达1;

存在多少种?

思路:

DFS+数学

对于小数据,我们一定敏感,k < min(8,n);

所以我们可以首先包搜出前k个的可能数,然后由于1,2的条件所以【1,k】与【k + 1,n】不会存在联系,而【k + 1,n】有(n - k)^(n - k)次方中可能,然后求成绩取余即可。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 107
#define N 10
using namespace std;

const int inf = 0x7f7f7f7f;
const int mod = 1000000007;
int a[N];
int n,k;
bool op[N];

ll ans;

void dfs(int ct)
{
    int i;
    if (ct == k)
    {
        for (i = 1; i <= k; ++i)
        {
            CL(op,false);
            op[1] = true;
            int p = a[i];
            while (!op[p])
            {
                op[p] = true;
                p = a[p];
            }
            if (p == 1) continue;
            else break;
        }
        if (i > k) ans++;
        return ;
    }
    for (i = 1; i <= k; ++i)
    {
        a[ct + 1] = i;
        dfs(ct + 1);
    }
}
int main()
{
//    Read();
//    Write();
    int i;
    while (~scanf("%d%d",&n,&k))
    {
        ans = 0;
        for (i = 1; i <= k; ++i)
        {
            a[1] = i;
            dfs(1);
        }
//        cout<<">>>>>>"<<ans<<endl;
        for (i = k + 1; i <= n; ++i)
        {
            ans = ans*(n - k)%mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

E:

题意:

输入n,求0-n的一个排列p0,p1 ...... pn,是的(0^p0) + (1^p1) + ......(n^pn)的值最大

思路:

贪心+位运算


我们只需要从最大的开始,找到他的二进制数的取反的数,然后让他们两个抑或即可取得最大值。

比赛的时候用了pow(2,i)来算2的i次幂,结果超时了,悲剧啊,以后还是尽量自己 写 pow2【】

 

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 107
#define N 1000007
using namespace std;

const int inf = 0x7f7f7f7f;

int a[N];
int pow2[22];
int b[22];

int main()
{
//    Read();
//    Write();
    for (int i = 0; i <= 20; ++i) pow2[i] = (1<<i);
    int n;
    int i,j,k;

    scanf("%d",&n);
    CL(a,-1);
    int len = 0;
    for (k = n; k >= 0; --k)
    {
        if (a[k] != -1) continue;
        len = 0;
        int tmp = k;
        while (tmp)
        {
            b[len++] = tmp%2;
            tmp/=2;
        }
//        for (i = len - 1; i >= 0; --i) printf(">>%d\n",b[i]);
        int no = 0;
        j = 0;
        for (i = 0; i < len; ++i)
        {
            no = b[i]*pow2[j] + no;
            j++;
        }
        int nm = 0;
        j = 0;
        for (i = 0; i < len; ++i)
        {
            nm = (!b[i])*pow2[j] + nm;
            j++;
        }
//        printf("%d %d\n",no,nm);
        a[no] = nm; a[nm] = no;
    }
    ll ans = 0;
    for (i = 0; i <= n; ++i)
    {
        if (a[i] != -1)
        {
            ans += (i^a[i]);
        }
        else
        {
            ans += (i^i);
            a[i] = i;
        }
    }
    cout<<ans<<endl;
    for (i = 0; i <= n; ++i) printf("%d ",a[i]);
    return 0;
}

 

 

posted @ 2013-04-05 12:07  E_star  阅读(288)  评论(0编辑  收藏  举报