国庆七天乐 Day2

今天做的是辽宁2010年的省赛题。题目难度比昨天容易了不少。悲哀的是,我们队只把前四道水题做出来了,

后面还有两道相对容易的题没做出来。

A : Dinner

A题是我敲的,开始看到题的时候还愣了一下,后面看到hint的提示,才发现如此之水。题意大致是给你N个盒子,

盒子里面放着一样东西,如果是餐具就输出,注意下格式就可以,餐具在hint中给出了,才四种...

#include <stdio.h>

#include <string.h>

#include <stdlib.h>



const char table[][15] = {"bowl", "knife", "fork", "chopsticks"};



int main()

{

    int n, cnt;

    char str[15];

    while(scanf("%d", &n) != EOF)

    {

        cnt = 0;

        while(n --)

        {

            scanf("%s", str);

            for(int i = 0; i < 4; i ++)

            {

                if(strcmp(str, table[i]) == 0)

                {

                    if(cnt ++)

                        printf(" ");

                    printf("%s", str);

                    break;

                }

            }

        }

        printf("\n");

    }

    return 0;

}

B : You are my brother

这道题是隽遒学弟敲的,他跟我说大致题意是给出N对关系,判断给定的两者的长幼关系,大致就是求到公共祖先的距离,然后按照题意输出一句话来表示两者的关系。

C:Time

这道题是陈兴做的,一道很纯的模拟题。将四个数字按照题意输出,先弄个表,然后打印就行了。

#include <cstdio>

#include <iostream>

#include <string>

using namespace std;

string dig[10][4];

void Prepare()

{

    dig[0][0] = " _ ";

    dig[0][1] = "| |";

    dig[0][2] = "|_|";



    dig[1][0] = "   ";

    dig[1][1] = "  |";

    dig[1][2] = "  |";



    dig[2][0] = " _ ";

    dig[2][1] = " _|";

    dig[2][2] = "|_ ";



    dig[3][0] = " _ ";

    dig[3][1] = " _|";

    dig[3][2] = " _|";



    dig[4][0] = "   ";

    dig[4][1] = "|_|";

    dig[4][2] = "  |";



    dig[5][0] = " _ ";

    dig[5][1] = "|_ ";

    dig[5][2] = " _|";



    dig[6][0] = " _ ";

    dig[6][1] = "|_ ";

    dig[6][2] = "|_|";



    dig[7][0] = " _ ";

    dig[7][1] = "  |";

    dig[7][2] = "  |";



    dig[8][0] = " _ ";

    dig[8][1] = "|_|";

    dig[8][2] = "|_|";



    dig[9][0] = " _ ";

    dig[9][1] = "|_|";

    dig[9][2] = " _|";

}

int main()

{

    int a[4];

    Prepare();

    while(scanf("%d%d%d%d", &a[0], &a[1], &a[2], &a[3]) != EOF)

    {

        for(int i = 0; i < 3; i++)

        {

            for(int j = 0; j < 4; j++)

            {

                cout << dig[a[j]][i];

            }

            putchar('\n');

        }

    }

    return 0;

}

D:SPY

这道题是我和隽遒学弟想出来的思路,然后陈兴敲的,因为我们两个都不会用STL的map,蛋疼,等会学一下,比我想写的hash简单方便多了。

题目给出三个集合,每个集合有一些字符串,要输出同在A和B中,但不在C中的字符串,即A并B - C。先将A的元素插入hash表中,再读入B,

再将C的元素插入hash表中,然后扫一边B,不在C表在A表中的输出。

#include <iostream>

#include <map>

#include <string>

using namespace std;

const int MAXN = 1 << 10;



string strb[MAXN];

int a, b, c;



int main()

{

    while(cin >> a >> b >> c)

    {

        map<string, int> hasha;

        map<string, int> hashc;

        string str;

        for(int i = 0; i < a; i ++)

        {

            cin >> str;

            hasha[str] = 1;

        }



        for(int i = 0; i < b; i ++)

        {

            cin >> strb[i];

        }



        for(int i = 0; i < c; i ++)

        {

            cin >> str;

            hashc[str] = 1;

        }



        int cnt = 0;

        for(int i = 0; i < b; i ++)

        {

            if(hasha[strb[i]] && !hashc[strb[i]])

            {

                if(cnt ++)

                    cout << " ";

                cout << strb[i];

            }

        }

        if(!cnt) cout << "No enemy spy";

        cout << endl;

    }

    return 0;

}

 

E:Intermediary

这道题比赛的时候想了很久还是不会。

F:English Game

AC自动机 + DP,隽遒学弟用Rabin-Karp写没过。

#include <stdio.h>

#include <string.h>



const int MAXN = 10010;

const int LEN = 32;

const int X = 10010;

//定义字典树

struct Trie

{

    int end;

    int v;

    struct Trie *son[26];

};



int n, nx;

int buf_cnt;

struct Trie *root, buf[MAXN * LEN];

int max[X];

char x[X];

//新建结点

struct Trie *New_node()

{

    struct Trie *tmp = &buf[buf_cnt ++];

    tmp -> end = 0;

    tmp -> v = 0;

    for(int i = 0; i < 26; i ++)

        tmp -> son[i] = 0;

    return tmp;

}

//插入字符串

void insert(char *s, int v)

{

    struct Trie *cur = root;

    for(int i = 0; s[i] != 0; i ++)

    {

        int id = s[i] - 'a';

        if(cur -> son[id] == NULL)

            cur -> son[id] = New_node();

        cur = cur -> son[id];

    }

    cur -> end = 1;

    cur -> v = v;

}

//翻转字符串

void reversal(char *s)

{

    int i = 0, j = strlen(s);

    j --;

    while(i < j)

    {

        char tmp = s[i];

        s[i] = s[j];

        s[j] = tmp;

        i ++, j --;

    }

}



void query(int i)

{

    struct Trie *cur = root;

    for(int j = i; x[j] != 0; j --)

    {

        int id = x[j] - 'a';

        if(cur -> son[id])

        {

            if(cur -> son[id] -> end)

            {

                if(max[j - 1] != -1)

                {

                    if(max[j - 1] + cur -> son[id] -> v > max[i])

                        max[i] = max[j - 1] + cur -> son[id] -> v;

                }

            }

            cur = cur -> son[id];

        }

        else break;

    }

}



int main()

{

    //freopen("test0.in", "r", stdin);

    //freopen("test.out", "wb", stdout);

    x[0] = 0;

    while(scanf("%d %s", &n, x + 1) != EOF)

    {

        nx = strlen(x + 1);

        buf_cnt = 0;

        root = New_node();

        for(int i = 0; i < n; i ++)

        {

            char s[LEN];

            int v;

            scanf("%s %d", s, &v);

            reversal(s);

            insert(s, v);

        }

        max[0] = 0;

        for(int i = 1; i <= nx; i ++)

        {

            max[i] = -1;

            query(i);

        }

        printf("%d\n", max[nx]);

    }

    return 0;

}

 

G:Friends number

最想吐槽的是这道题,我还傻傻的去找规律,最后问了斌牛说打表只需几秒就行。亲和数,真因子之和等于对方的一对数。开始一直在想5000000的

数据范围怎么搞定,后面发现无法搞定。我还是图样图森破...

打表和筛选素数的方法类似:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <iostream>

using namespace std;

const int MAXN = 5000000;

int sum[MAXN + 10];



int main()

{

    freopen("data.txt", "w", stdout);

    int i, j;

    for (i = 0; i <= MAXN ; i ++)

        sum[i] = 1;  //1是所有数的真因数所以全部置1



    for (i = 2; i + i <= MAXN; i ++)

    {

        j = i + i;  //因为真因数,所以不能算本身,所以从它的2倍开始

        while (j <= MAXN)

        {

            //将所有i的倍数的位置上加i

            sum[j] += i;

            j += i;

        }

    }



    for (i = 220; i <= MAXN; i++)   //扫描,O(N)。

    {

        // 一次遍历,因为知道最小是220和284因此从220开始

        if (sum[i] > i && sum[i] <= MAXN && sum[sum[i]] == i)

        {

            //去重,不越界,满足亲和

            cout << i << ", " << sum[i] << "," << endl;

        }

    }

    return 0;

}

打出表之后,直接判断这些数在不在给定的[a,b]内就行了,500万内的亲和数对也不多,才71对。

#include <stdio.h>

#include <string.h>

#include <stdlib.h>



const int pt[][2] =

{

    220, 284,

    1184, 1210,

    2620, 2924,

    5020, 5564,

    6232, 6368,

    10744, 10856,

    12285, 14595,

    17296, 18416,

    63020, 76084,

    66928, 66992,

    67095, 71145,

    69615, 87633,

    79750, 88730,

    100485, 124155,

    122265, 139815,

    122368, 123152,

    141664, 153176,

    142310, 168730,

    171856, 176336,

    176272, 180848,

    185368, 203432,

    196724, 202444,

    280540, 365084,

    308620, 389924,

    319550, 430402,

    356408, 399592,

    437456, 455344,

    469028, 486178,

    503056, 514736,

    522405, 525915,

    600392, 669688,

    609928, 686072,

    624184, 691256,

    635624, 712216,

    643336, 652664,

    667964, 783556,

    726104, 796696,

    802725, 863835,

    879712, 901424,

    898216, 980984,

    947835, 1125765,

    998104, 1043096,

    1077890, 1099390,

    1154450, 1189150,

    1156870, 1292570,

    1175265, 1438983,

    1185376, 1286744,

    1280565, 1340235,

    1328470, 1483850,

    1358595, 1486845,

    1392368, 1464592,

    1466150, 1747930,

    1468324, 1749212,

    1511930, 1598470,

    1669910, 2062570,

    1798875, 1870245,

    2082464, 2090656,

    2236570, 2429030,

    2652728, 2941672,

    2723792, 2874064,

    2728726, 3077354,

    2739704, 2928136,

    2802416, 2947216,

    2803580, 3716164,

    3276856, 3721544,

    3606850, 3892670,

    3786904, 4300136,

    3805264, 4006736,

    4238984, 4314616,

    4246130, 4488910,

    4259750, 4445050,

};



int main()

{

    int a, b;

    while(scanf("%d%d", &a, &b) != EOF)

    {

        int cnt = 0;

        for(int i = 0; i < 71; i ++)

        {

            if(pt[i][0] >= a && pt[i][0] <= b && pt[i][1] >= a && pt[i][1] <= b)

            {

                cnt ++;

            }

        }

        printf("%d\n", cnt);

    }

    return 0;

}

 

H:Happiness Hotel

推出公式是 x^2 - dy^2 = 1,传说中的佩尔方程,不会求他的最小解...

I:NEW RDSP MODE I

 

#include <stdio.h>

#include <string.h>

#include <stdlib.h>



typedef long long LL;



LL PowMod(LL a, LL n, LL mod)

{

    LL ret = 1;

    while(n)

    {

        if(n & 1) ret = ret * a % mod;

        a = a * a % mod;

        n >>= 1;

    }

    return ret;

}



LL n, m, k;

int main()

{

    while(scanf("%lld%lld%lld", &n, &m, &k) != EOF)

    {

        if(n % 2 == 0) n ++;

        LL t = PowMod(2, m, n);

        if(t == 0) t = n;

        for(int i = 1; i <= k; i ++)

        {

            if(i != 1)

                printf(" ");

            LL ans = t * i % n;

            if(ans == 0) ans = n;

            printf("%lld", ans);

        }

        printf("\n");

    }

    return 0;

}

你可能感兴趣的:(a)