• 正确答案 全国信息学奥林匹克联赛( ( NOIP2014) 复 赛 模拟题 Day1 长乐一中


    【题目描述】
    小 H 与小 Y 刚刚参加完 UOIP 外卡组的初赛,就迫不及待的跑出考场对答案。
    “吔,我的答案和你都不一样!”,小 Y 说道,”我们去找神犇们问答案吧”。
    外卡组试卷中共有 m 道判断题,小 H 与小 Y 一共从其他 n 个神犇那问了答案。之后又
    从小 G 那里得知, 这 n 个神犇中有 p 个考了满分, q 个考了零分, 其他神犇不为满分或零分。
    这可让小 Y 与小 H 犯了难。你能帮助他们还原出标准答案吗?如有多解则输出字典序最小
    的那个。无解输出-1。
    【 输入格式】
    第一行四个整数 n, m, p, q,意义如上描述。
    接下来 n 行,每一行 m 个字符’N’或’Y’,表示这题这个神犇的答案。
    【 输出格式】
    仅一行,一个长度为 m 的字符串或是-1。
    【 样例输入】
    2 2 2 0
    YY
    YY
    【 样例输出】
    YY
    【 数据范围】
    30% : n <= 100.
    60% : n <= 5000 , m <= 100.
    100% : 1 <= n <= 30000 , 1 <= m <= 500. 0 <= p , q 且 p + q <= n.

    長樂一中給出的解析:

    30%: O(n ^ 2 * m)暴力判断。
    100%: 很显然答案的可能性最多只有 n 种,所以我们将所有人的答案按字典序排序后枚举
    将每个人的答案作为正确答案来进行判断。 由于是判断题, 若当前人的答案为正确答
    案则零分者的答案也就确定了, 那么只需统计出这两种答案的人数判断是否满足题意
    即可。这一步使用字符串哈希即可解决。
    另外要注意 p = 0 和 p = q = 0 的情况。

    長樂一中給出的正解代碼:

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <cmath>
      6 using namespace std;
      7 
      8 const int N = 3e4 + 2, M = 5e2 + 2, sed = 31, SED = 131, mod = 70177, MOD = 92311;
      9 int n, m, p, q, ans, hash[N], HASH[N];
     10 int top, info[mod], nxt[N * 2], fet[N * 2], cnt[N * 2];
     11 struct node {
     12 char s[M];
     13 inline bool operator < (const node &b) const {
     14 return strcmp(s, b.s) < 0;
     15 }
     16 } a[N];
     17 
     18 inline void Insert(const int &x, const int &y) {
     19 for (int k = info[x]; k; k = nxt[k])
     20 if (fet[k] == y) {
     21 ++cnt[k]; return ;
     22 }
     23 nxt[++top] = info[x]; info[x] = top;
     24 fet[top] = y; cnt[top] = 1;
     25 return ;
     26 }
     27 
     28 inline int Query(const int &x, const int &y) {
     29 for (int k = info[x]; k; k = nxt[k])
     30 if (fet[k] == y) return cnt[k];
     31 return 0;
     32 }
     33 
     34 inline void Solve1() {
     35 int tmp, TMP; ans = -1;
     36 for (int i = 0; i < n; ++i) {
     37 tmp = TMP = 0;
     38 for (int j = 0; j < m; ++j) {
     39 tmp = (tmp * sed + (a[i].s[j] == 'N')) % mod;
     40 TMP = (TMP * SED + (a[i].s[j] == 'N')) % MOD;
     41 }
     42 hash[i] = tmp, HASH[i] = TMP;
     43 Insert(tmp, TMP);
     44 }
     45 for (int i = 0; i < n; ++i)
     46 if (Query(hash[i], HASH[i]) == p) {
     47 tmp = TMP = 0;
     48 for (int j = 0; j < m; ++j) {
     49 tmp = (tmp * sed + (a[i].s[j] == 'Y')) % mod;
     50 TMP = (TMP * SED + (a[i].s[j] == 'Y')) % MOD;
     51 }
     52 if (Query(tmp, TMP) == q) {
     53 ans = i; break;
     54 }
     55 }
     56 if (ans != -1) printf("%s
    ", a[ans].s);
     57 else puts("-1");
     58 return ;
     59 }
     60 
     61 char cur[M];
     62 inline void Solve2() {
     63 int tmp, TMP; ans = -1;
     64 for (int i = 0; i < n; ++i) {
     65 tmp = TMP = 0;
     66 for (int j = 0; j < m; ++j) {
     67 tmp = (tmp * sed + (a[i].s[j] == 'N')) % mod;
     68 TMP = (TMP * SED + (a[i].s[j] == 'N')) % MOD;
     69 }
     70 hash[i] = tmp, HASH[i] = TMP;
     71 Insert(tmp, TMP);
     72 }
     73 for (int i = n - 1; i >= 0; --i)
     74 if (Query(hash[i], HASH[i]) == q) {
     75 tmp = TMP = 0;
     76 for (int j = 0; j < m; ++j) {
     77 tmp = (tmp * sed + (a[i].s[j] == 'Y')) % mod;
     78 TMP = (TMP * SED + (a[i].s[j] == 'Y')) % MOD;
     79 }
     80 if (Query(tmp, TMP) == p) {
     81 ans = i; break;
     82 }
     83 }
     84 if (ans != -1) {
     85 for (int i = 0; i < m; ++i)
     86 cur[i] = a[ans].s[i] == 'N' ? 'Y' : 'N';
     87 printf("%s
    ", cur);
     88 }
     89 else puts("-1");
     90 return ;
     91 }
     92 
     93 void Solve3() {
     94 int tmp, TMP;
     95 for (int i = 0; i < n; ++i) {
     96 tmp = TMP = 0;
     97 for (int j = 0; j < m; ++j) {
     98 tmp = (tmp * sed + (a[i].s[j] == 'N')) % mod;
     99 TMP = (TMP * SED + (a[i].s[j] == 'N')) % MOD;
    100 }
    101 Insert(tmp, TMP);
    102 tmp = TMP = 0;
    103 for (int j = 0; j < m; ++j) {
    104 tmp = (tmp * sed + (a[i].s[j] == 'Y')) % mod;
    105 TMP = (TMP * SED + (a[i].s[j] == 'Y')) % MOD;
    106 }
    107 Insert(tmp, TMP);
    108 }
    109 bool flag = true;
    110 for (int i = 0; i < m; ++i) cur[i] = 'N';
    111 do {
    112 tmp = TMP = 0;
    113 for (int j = 0; j < m; ++j) {
    114 tmp = (tmp * sed + (cur[j] == 'N')) % mod;
    115 TMP = (TMP * SED + (cur[j] == 'N')) % MOD;
    116 }
    117 if (Query(tmp, TMP) == 0) {
    118 flag = true; break;
    119 }
    120 flag = false;
    121 for (int j = m - 1; j >= 0; --j)
    122 if (cur[j] == 'Y') cur[j] = 'N';
    123 else {
    124 cur[j] = 'Y'; flag = true; break;
    125 }
    126 } while (flag);
    127 if (flag) printf("%s
    ", cur);
    128 else puts("-1");
    129 return ;
    130 }
    131 
    132 int main() {
    133 freopen("answer.in", "r", stdin);
    134 freopen("answer.out", "w", stdout);
    135 scanf("%d%d%d%d", &n, &m, &p, &q);
    136 for (int i = 0; i < n; ++i) scanf("%s", a[i].s);
    137 sort(a, a + n);
    138 if (p) Solve1();
    139 else if (q) Solve2();
    140 else Solve3();
    141 fclose(stdin); fclose(stdout);
    142 return 0;
    143 }
    View Code

    代碼實現:

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,m,p,q,a,z=1;
    char ch[500],cn[500];
    string st[30000];//儲存每個答案。 
    map <string,int> mm;//儲存每種答案出現的次數。 
    void part_1(){
    for(int i=0;i<n;i++){//順序枚舉。 
    if(mm[st[i]]==p){ //假如當前答案的出現數等於正解數, 
    for(int j=0;j<m;j++){//ch中是這個答案的錯排。 
    if(st[i][j]=='N') ch[j]='Y';
    else ch[j]='N';
    }
    if(mm[ch]==q){cout<<st[i]<<endl;return;}//並且它的錯排的出現數等於報零答案數,可以認為這是正解。 
    }
    }
    printf("-1
    ");//如果沒有找到,即p,q不合法,輸出負一。 
    }
    void part_2(){
    for(int i=0;i<n;i++){
    if(mm[st[i]]==q){//如果當前答案的出現數等於報零答案數, 
    for(int j=0;j<m;j++){
    if(st[i][j]=='N') ch[j]='Y';
    else ch[j]='N';
    }
    if(!mm[cn]){cout<<ch<<endl;return;}//並且它的錯排,即正解,沒有出現過,則它的錯排合法。
    }
    }
    printf("-1
    ");//對於數據,並無意義。 
    }
    void part_3(){//正解和報零答案都沒有出現過,所以要捋一下全排列。 
    for(int i=0;i<m;i++){
    cn[i]='N';//從字典序排列時最前面的先拿出。 
    z*=2;//z等於二的m次冪。 
    }
    for(int i=0;i<z/2;i++){//小於z可以理解,因為這是一個類似01字串的字符串。 
    a=m-1;cn[a]+='Y'-'N';
    while(cn[a]==2*'Y'-'N'&&a>0){
    cn[a--]='N';
    cn[a]+='Y'-'N';
    }//因為有錯排,所以是小於z/2。 
    for(int j=0;j<m;j++){
    if(cn[j]=='N') ch[j]='Y';
    else ch[j]='N';
    }
    if(!mm[cn]&&!mm[ch]){cout<<cn<<endl;return;}//如果該排列即其錯排都為出現個,則該排列合法。 
    }
    printf("-1
    ");//對於數據,並無意義。 
    }
    int main(){
    freopen("answer.in","r",stdin);
    freopen("answer.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for(int i=0;i<n;i++){
    scanf("%s",&ch);//一種比較簡單的讀入技巧,時間大概是直接cin流輸入的三分之一。 
    for(int j=0;j<m;j++) st[i]+=ch[j];
    ++mm[st[i]];//記錄重新次數。 
    }
    sort(st,st+n);//因為答案要按字典序輸出,所以排一下序。 
    if(p) part_1();
    if(!p&&q) part_2();
    if(!p&&!q) part_3();
    return 0;
    }
    View Code

    吐槽一下,這個答案很多時候并並不正確。

  • 相关阅读:
    最小生成树(模板)
    排序
    kmp模板
    图书管理系统
    顺序表的创建
    洛谷p1090合并果子(优先队列或堆)
    洛谷P1464Function(逆向递推递归+记忆化)
    ueditor设置
    php isset()和 in_array()
    php 判断空
  • 原文地址:https://www.cnblogs.com/J-william/p/6062585.html
Copyright © 2020-2023  润新知