正确答案 全国信息学奥林匹克联赛( ( 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 的情况。
長樂一中給出的正解代碼:
#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 长乐一中的更多相关文章
- 全国信息学奥林匹克联赛 ( NOIP2014) 复赛 模拟题 Day1 长乐一中
题目名称 正确答案 序列问题 长途旅行 英文名称 answer sequence travel 输入文件名 answer.in sequence.in travel.in 输出文件名 answer. ...
- 全国信息学奥林匹克联赛(NOIP2014)复赛 模拟题Day2 长乐一中
题目名称 改造二叉树 数字对 交换 英文名称 binary pair swap 输入文件名 binary.in pair.in swap.in 输出文件名 binary.out pair.out sw ...
- 第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题
第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 1.原题呈现 2.试题答案 3.题目解析 因博客园无法打出公式等,所以给你们几个小编推荐的链接去看看,在这里小编深感抱歉! https ...
- 巨坑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 ...
- 正确答案 [Hash/枚举]
正确答案 题目描述 小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案. "吔,我的答案和你都不一样!",小Y说道,"我们去找神犇们问答案吧" ...
- PMP全真模拟题真题試題含答案解析 2019年下半年PMP考試适用 PMP中文文对照试题 【香港台灣地區PMP考試也可用】
PMP全真模拟题真题试题 含答案解析 2019年下半年PMP考试适用 PMP中文文对照试题 [香港台灣地區PMP考試也可用]PMP全真模擬題真題試題 含答案解析 2019年下半年PMP考試适用 PMP ...
- 全国青少年信息学奥林匹克分区联赛(N)竞赛大纲
全国青少年信息学(计算机)奥林匹克分区联赛竞赛大纲 一.初赛内容与要求:(#表示普及组不涉及,以下同) 计算机的基本发展 诞生与发展 特点 在现代社会中的应用 计算机系统的基本组成 计算机的工作原理# ...
- java能不能自己写一个类叫java.lang.System/String正确答案
原文: http://www.wfuyu.com/php/22254.html 未做测试 ! 最近学习了下java类加载相干的知识.然后看到网上有1道面试题是 能不能自己写个类叫java.lang.S ...
- JS不用通过其他转换两个小数加减得到正确答案
之前写过一篇文章js比较两个属于float类型的小数,都需要通过某种函数转换下,太麻烦了,比如: 减法:10.2345-0.01=10.2245,这是正确的答案,但是当你做加法的时候就变了 加法:10 ...
随机推荐
- C++-前缀和后缀
1,c++规定后缀形式的++操作符有一个int行的参数,被调用时,编译器自动加一个0作为参数给他 2,前缀返回一个reference,后缀返回一个const对象 /////////////////// ...
- Chart For Asp.Net ----Overview
一个图表有很多元素构成,所有元素都能通过图表API控制.图表API是面向对象的,可扩展的,高复用的.支持很多图表元素如:data series,data points in a series,char ...
- java面试题之ssh
1.写出你熟悉的开源框架以及各自的作用(项目中为什么使用SSH) 答:框架:hibernate,spring,struts1/struts2. Hibernate主要用于数据持久化:封装了JDBC操作 ...
- 重拾java系列一java基础(3)
这一章主要复习下以前所接触的算法, (1)选择排序法:在要排序的一组数中,选出最小的一个数与第一个位置的数交换:然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较 ...
- 2016 - 1- 14 UI阶段学习补充 transform属性详解
UIView的transform属性 transform是view的一个重要属性,它在矩阵层面上改变view的显⽰状态,能实现view的缩放.旋转.平移等功能.transform是CGAffineTr ...
- String to Integer (atoi) ---- LeetCode 008
Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...
- Swift编程规范
文档编号: 应用开发Swift编码规范 (版本v1.0.0) 成文信息 主题词: Swift开发编码规范 作 者: 周少停 文档类别: 开发规范 审 核: 批 准: 文档性质: 初稿 ...
- XMLParser解析xml--内容源自网络(在静态库中不能用GDATA来解析,因为静态库不能加动态库)
</Books> 从其文档结构我们可以看出,要定义一个Book实体类描述具体的书籍信息,其中用于存储的相关xml文档元素的实例变量与对应元素同名(本例:title.author.summa ...
- Codeforces 699
Problem A Launch of Collider 题目大意 在x轴上有n个点,坐标均为偶数.每个点或向左移动或向右移动,每秒移动距离为1. 使所有点同时开始移动,求最早有点相遇的时间或无解. ...
- CODEVS1533 互斥的数(哈希表)
给定一个集合,要求一个最大子集,满足两两之间不互斥.对两个数x,y互斥的定义是,y=p*x. 先对集合中的数从小到大排序后线性扫,若一个数x可以取则取,取完之后p*x这个数不可取.由于数字较大,使用哈 ...