【题目描述】
小 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. wp8.1 Study6: App的生命周期管理

    一.概述 应用程序的生命周期详解可以参照Windows8.1开发中msdn文档http://msdn.microsoft.com/library/windows/apps/hh464925.aspx ...

  2. static inline

    今天看到了这样一段代码, static inline BOOL IsEmpty(id thing) { return thing == nil || [thing isEqual:[NSNull nu ...

  3. git 克隆项目 与 分支简单操作

    git clone http://abcde.com/myproject/abc.git 克隆远程项目到本地githome文件夹git branch -a 查看所有分支 包括远程和本地 *号开头表示当 ...

  4. ios 检测应用程序升级问题

    app 上其实已经有自动检测我们版本的功能.  其实我也觉得对于一个程序员来说检测功能让,系统来维护更合适和合理.开发者只要告诉苹果即可. 然而今天老大非要实现自己版本更新的问题,因此也查找了相关的资 ...

  5. 【python】dict。字典

    特点:以空间换取时间,使用HASH算法通过key算出了value的内存地址,建立索引,拿到key后查找速度快,但内存浪费多 因为是用key值算的内存地址,所以key为不可变变量 (set,和dict类 ...

  6. 系统的 host文件的作用

    有些用户可能已经注意到,我们在上网时除了可使用常规的 http://www.xxx.com或http://www.xxx.com.cn等形式的网站域名之外,还可以使用类似于“202.106.184.2 ...

  7. Ogre碰撞检测

    转自:http://blog.csdn.net/weiqubo/article/details/7108363 Ogre采用树桩管理场景中的各种"元素"(摄像机.灯光.物体等),所 ...

  8. hdu 2056

    ps:    - -惭愧...是套用一个大神的计算方法来做的.....下面是代码 代码: #include "stdio.h"#include "stdlib.h&quo ...

  9. HackRF实现无线门铃信号分析重放

    文章特点:数据解码方面实在是没什么信心,存在分析错乱的可能性,所幸发出来共同探讨,恳请鞭策. 0x01 概述 这是一款工作在315Mhz频段的无线遥控门铃,根据查阅官方手册以及芯片信息,确定其采用了e ...

  10. osmocom-bb中用osmocon刷入固件命令那些参数你都弄懂了吗?

    转载留做备份,原文地址:http://92ez.com/?action=show&id=23341 首先找到osmocon.c这个源文件,具体目录在这里 osmocom-bb/src/host ...