【题目描述】
小 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 的情况。

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

 #include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std; const int N = 3e4 + , M = 5e2 + , sed = , SED = , mod = , MOD = ;
int n, m, p, q, ans, hash[N], HASH[N];
int top, info[mod], nxt[N * ], fet[N * ], cnt[N * ];
struct node {
char s[M];
inline bool operator < (const node &b) const {
return strcmp(s, b.s) < ;
}
} a[N]; inline void Insert(const int &x, const int &y) {
for (int k = info[x]; k; k = nxt[k])
if (fet[k] == y) {
++cnt[k]; return ;
}
nxt[++top] = info[x]; info[x] = top;
fet[top] = y; cnt[top] = ;
return ;
} inline int Query(const int &x, const int &y) {
for (int k = info[x]; k; k = nxt[k])
if (fet[k] == y) return cnt[k];
return ;
} inline void Solve1() {
int tmp, TMP; ans = -;
for (int i = ; i < n; ++i) {
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (a[i].s[j] == 'N')) % mod;
TMP = (TMP * SED + (a[i].s[j] == 'N')) % MOD;
}
hash[i] = tmp, HASH[i] = TMP;
Insert(tmp, TMP);
}
for (int i = ; i < n; ++i)
if (Query(hash[i], HASH[i]) == p) {
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (a[i].s[j] == 'Y')) % mod;
TMP = (TMP * SED + (a[i].s[j] == 'Y')) % MOD;
}
if (Query(tmp, TMP) == q) {
ans = i; break;
}
}
if (ans != -) printf("%s\n", a[ans].s);
else puts("-1");
return ;
} char cur[M];
inline void Solve2() {
int tmp, TMP; ans = -;
for (int i = ; i < n; ++i) {
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (a[i].s[j] == 'N')) % mod;
TMP = (TMP * SED + (a[i].s[j] == 'N')) % MOD;
}
hash[i] = tmp, HASH[i] = TMP;
Insert(tmp, TMP);
}
for (int i = n - ; i >= ; --i)
if (Query(hash[i], HASH[i]) == q) {
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (a[i].s[j] == 'Y')) % mod;
TMP = (TMP * SED + (a[i].s[j] == 'Y')) % MOD;
}
if (Query(tmp, TMP) == p) {
ans = i; break;
}
}
if (ans != -) {
for (int i = ; i < m; ++i)
cur[i] = a[ans].s[i] == 'N' ? 'Y' : 'N';
printf("%s\n", cur);
}
else puts("-1");
return ;
} void Solve3() {
int tmp, TMP;
for (int i = ; i < n; ++i) {
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (a[i].s[j] == 'N')) % mod;
TMP = (TMP * SED + (a[i].s[j] == 'N')) % MOD;
}
Insert(tmp, TMP);
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (a[i].s[j] == 'Y')) % mod;
TMP = (TMP * SED + (a[i].s[j] == 'Y')) % MOD;
}
Insert(tmp, TMP);
}
bool flag = true;
for (int i = ; i < m; ++i) cur[i] = 'N';
do {
tmp = TMP = ;
for (int j = ; j < m; ++j) {
tmp = (tmp * sed + (cur[j] == 'N')) % mod;
TMP = (TMP * SED + (cur[j] == 'N')) % MOD;
}
if (Query(tmp, TMP) == ) {
flag = true; break;
}
flag = false;
for (int j = m - ; j >= ; --j)
if (cur[j] == 'Y') cur[j] = 'N';
else {
cur[j] = 'Y'; flag = true; break;
}
} while (flag);
if (flag) printf("%s\n", cur);
else puts("-1");
return ;
} int main() {
freopen("answer.in", "r", stdin);
freopen("answer.out", "w", stdout);
scanf("%d%d%d%d", &n, &m, &p, &q);
for (int i = ; i < n; ++i) scanf("%s", a[i].s);
sort(a, a + n);
if (p) Solve1();
else if (q) Solve2();
else Solve3();
fclose(stdin); fclose(stdout);
return ;
}

代碼實現:

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

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

正确答案 全国信息学奥林匹克联赛( ( NOIP2014) 复 赛 模拟题 Day1 长乐一中的更多相关文章

  1. 全国信息学奥林匹克联赛 ( NOIP2014) 复赛 模拟题 Day1 长乐一中

    题目名称 正确答案  序列问题 长途旅行 英文名称 answer sequence travel 输入文件名 answer.in sequence.in travel.in 输出文件名 answer. ...

  2. 全国信息学奥林匹克联赛(NOIP2014)复赛 模拟题Day2 长乐一中

    题目名称 改造二叉树 数字对 交换 英文名称 binary pair swap 输入文件名 binary.in pair.in swap.in 输出文件名 binary.out pair.out sw ...

  3. 第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题

    第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 1.原题呈现 2.试题答案 3.题目解析 因博客园无法打出公式等,所以给你们几个小编推荐的链接去看看,在这里小编深感抱歉! https ...

  4. 巨坑npm run dev 报错 终于找到正确答案 Error: EPERM: operation not permitted, open '/data/public/build/css/add.p

    Windows10环境 npm run dev 报错  终于找到正确答案 Error: EPERM: operation not permitted, open '/data/public/build ...

  5. 正确答案 [Hash/枚举]

    正确答案 题目描述 小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案. "吔,我的答案和你都不一样!",小Y说道,"我们去找神犇们问答案吧" ...

  6. PMP全真模拟题真题試題含答案解析 2019年下半年PMP考試适用 PMP中文文对照试题 【香港台灣地區PMP考試也可用】

    PMP全真模拟题真题试题 含答案解析 2019年下半年PMP考试适用 PMP中文文对照试题 [香港台灣地區PMP考試也可用]PMP全真模擬題真題試題 含答案解析 2019年下半年PMP考試适用 PMP ...

  7. 全国青少年信息学奥林匹克分区联赛(N)竞赛大纲

    全国青少年信息学(计算机)奥林匹克分区联赛竞赛大纲 一.初赛内容与要求:(#表示普及组不涉及,以下同) 计算机的基本发展 诞生与发展 特点 在现代社会中的应用 计算机系统的基本组成 计算机的工作原理# ...

  8. java能不能自己写一个类叫java.lang.System/String正确答案

    原文: http://www.wfuyu.com/php/22254.html 未做测试 ! 最近学习了下java类加载相干的知识.然后看到网上有1道面试题是 能不能自己写个类叫java.lang.S ...

  9. JS不用通过其他转换两个小数加减得到正确答案

    之前写过一篇文章js比较两个属于float类型的小数,都需要通过某种函数转换下,太麻烦了,比如: 减法:10.2345-0.01=10.2245,这是正确的答案,但是当你做加法的时候就变了 加法:10 ...

随机推荐

  1. Enumeration 接口

    Enumeration是遍历集合元素的一种方法. Enumeration中只有两个方法: 1.hasMoreElements()  测试此枚举是否包含更多的元素. 2.nextElement()  如 ...

  2. linux的简单网络配置

    1,修改IP edit file: # if rh family system /etc/sysconfig/network-scripts/ifcfg-eth0 (eth0可能会是别的名字) # i ...

  3. 教学目标的表述方式──行为目标的ABCD表述法

    教学目标应规定学生在教学活动结束后能表现出什么样的学业行为,并限定学生学习过程中知识.技能的获得和情感态度发展的层次.范围.方式及变化效果的量度.对每节课教学目标的准确表述,可以充分发挥教学目标在教学 ...

  4. 《Head First设计模式(中文版)》

    <Head First设计模式(中文版)>共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式.前言先介绍<Head First设计模式(中文版)>的 ...

  5. 重拾java系列一java基础(1)

    前言,不知不觉,从接触java到工作至今已有两年的时间,突然感觉自己的基础知识还很薄弱,有些知识虽然知道,但是停留在表面上,没有深挖,或者实践过,感觉掌握的很肤浅,而且时间一长,就觉得忘记了,我觉得这 ...

  6. EventBus vs Otto vs LiteEventBus

    http://blog.chengyunfeng.com/?p=449 http://litesuits.com/

  7. (spring-第4回【IoC基础篇】)spring基于注解的配置

    基于XML的bean属性配置:bean的定义信息与bean的实现类是分离的. 基于注解的配置:bean的定义信息是通过在bean实现类上标注注解实现. 也就是说,加了注解,相当于在XML中配置了,一样 ...

  8. 使用Qemu调试内核

    利用Qemu进行内核源码级调试 http://blog.csdn.net/gdt_a20/article/details/7231652 用Qemu调试Linux内核 http://blog.chin ...

  9. android手机连接PC无法正常安装驱动

    工作当中我们经常会遇到Android手机连接PC的时候无法正确安装驱动,或者安装失败.当然找到正确的驱动文件时首选的解决方案,如果正确的驱动文件依旧无法安装成功我们可以打开我的电脑-->属性-- ...

  10. JAVA的第一个程序

    关于下载安装环境变量的配置网上的教程已经很多了 . 下面附上第一个HelloWorld的代码 /** 这是我的第一个java程序 */ public class HelloWorld { public ...