NOIP 2018 及历年赛题详细题目下载 -提取码:ajfb
【题目描述】
小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.
暴力50:
/*
自己还是太弱~没看出来要用hash 只是觉得自己的作法慢~
QAQ
50分暴力 先排序 一样的缩成一种 然后枚举正确答案是哪个
q == 0 p == 0的情况没考虑到~
*/
#include< iostream>
#include< cstdio>
#include< cstring>
#include< algorithm>
#define maxn 30010
#define maxm 510
using namespace std;
int n,m,p,q,cnt;
string g[maxn];
struct node{
int len;
string s;
}k[maxn];
int cmp(int a[maxm],int b[maxm]){
for(int i=1;i<=m;i++){
if(a[i] if(a[i]>b[i])return 0;
}
return 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=1;i<=n;i++)cin>>g[i];
sort(g+1,g+1+n);
int l=1,r;
for(r=2;r<=n;r++){
if(g[r] == g[l])continue;
k[++cnt].s=g[l];
k[cnt].len=r-l;l=r;
}
k[++cnt].s=g[l];
k[cnt].len=r-l;
int falg=0;
for(int i=1;i<=cnt;i++){
if(k[i].len!=p)continue;
int sum=0;
string x;x.clear();
for(int j=0;j
else x+=‘Y’;
for(int j=1;j<=cnt;j++)
if(k[j].s == x){
sum+=k[j].len;
break;
}
if(sum == q){
cout<
}
}
if(falg == 0)
for(int i=1;i<=cnt;i++){
if(k[i].len!=q)continue;
int sum=0;
string x;x.clear();
for(int j=0;j
else x+=‘Y’;
for(int j=1;j<=cnt;j++)
if(k[j].s == x){
sum+=k[j].len;
break;
}
if(sum==p){
cout<
}
}
if(!falg)printf("-1\n");
return 0;
}
正解hash:
/*
正解hash
思路和之前的有相似之处
先排序 只不过没有类似离散化的处理
把每个人的答案放入hash表 这里用链表处理了碰撞的情况
然后同样的枚举正确答案 这不过用了hash表加速
对于pq == 0的情况 枚举答案 按字典序小的来
那难道不会T到飞吗 不成了2^500的了吗
答案是不会的 这里的枚举是针对pq == 0的情况来的
结束的条件是 找到与每个人都不一样的(存在一个即可)的就停下
所以枚举最多30000次
/
#include< iostream>
#include< cstdio>
#include< cstring>
#include< algorithm>
#define maxn 100010
#define mod 10007
#define MOD 23333
#define bas 19
#define BAS 119
using namespace std;
int n,m,p,q,hash[maxn],HASH[maxn],ans,falg;
int num,head[maxn],cnt[maxn],t,T;
struct edge{
int v,pre;
}e[maxn2];
struct node{
char s[510];
bool operator < (const node &x) const {
return strcmp(s,x.s)<0;
}
}a[maxn];
void Insert(int from,int to){
for(int i=head[from];i;i=e[i].pre)
if(e[i].v == to){
cnt[i]++;return;
}
num++;e[num].v=to;
e[num].pre=head[from];
head[from]=num;
cnt[num]++;
}
int Query(int from,int to){
for(int i=head[from];i;i=e[i].pre)
if(e[i].v == to)return cnt[i];
return 0;
}
void Yan(){
for(int i=1;i<=n;i++){
t=0,T=0;
for(int j=0;j
T=TBAS+(a[i].s[j] == ‘Y’);T%=MOD;
}
hash[i]=t;HASH[i]=T;
Insert(t,T);
}
for(int i=1;i<=n;i++){
if(Query(hash[i],HASH[i]) == p){
int t=0,T=0;
for(int j=0;j
T=TBAS+(a[i].s[j] == ‘N’);T%=MOD;
}
if(Query(t,T) == q){
ans=i;
falg=1;break;
}
if(falg)break;
}
}
if(falg)printf("%s\n",a[ans].s);
else printf("-1\n");
}
void Li(){
for(int i=1;i<=n;i++){
int t=0,T=0;
for(int j=0;j
T=TBAS+(a[i].s[j] == ‘Y’);T%=MOD;
}
hash[i]=t;HASH[i]=T;
Insert(t,T);
}
for(int i=n;i>=1;i–){
if(Query(hash[i],HASH[i]) == q){
t=0,T=0;
for(int j=0;j
T=TBAS+(a[i].s[j]== ‘N’);T%=MOD;
}
if(Query(t,T)== p){
ans=i;
falg=1;break;
}
if(falg)break;
}
}
if(falg){
for(int i=0;i
else printf(“N”);
}
else printf("-1\n");
}
void Feng(){
for(int i=1;i<=n;i++){
t=0,T=0;
for(int j=0;j
T=TBAS+(a[i].s[j]== ‘Y’);T%=MOD;
}
Insert(t,T);
t=0;T=0;
for(int j=0;j
T=TBAS+(a[i].s[j]== ‘N’);T%=MOD;
}
Insert(t,T);
}
char r[510];
for(int i=0;i
t=0,T=0;
for(int i=0;i
T=TBAS+(r[i]== ‘Y’);T%=MOD;
}
if(Query(t,T)== 0){
falg=1;break;
}
for(int i=m-1;i>=0;i–)
if(r[i]==‘Y’)r[i]=‘N’;
else{
r[i]=‘Y’;break;
}
}
if(falg)printf("%s\n",r);
else 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=1;i<=n;i++)
scanf("%s",a[i].s);
sort(a+1,a+1+n);
if§Yan();
else if(q)Li();
else Feng();
return 0;
}