1. 程式人生 > >noip-模擬試題之--正確答案

noip-模擬試題之--正確答案

2018 NOIP 全套資料下載

【題目描述】

小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]<b[i])return 1;
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<m;j++)
if(k[i].s[j] == ‘Y’)x+=‘N’;
else x+=‘Y’;
for(int j=1;j<=cnt;j++)
if(k[j].s == x){
sum+=k[j].len;
break;
}
if(sum == q){
cout<<k[i].s;
falg=1;break;
}
}
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<m;j++)
if(k[i].s[j] == ‘Y’)x+=‘N’;
else x+=‘Y’;
for(int j=1;j<=cnt;j++)
if(k[j].s == x){
sum+=k[j].len;
break;
}
if(sum==p){
cout<<x;
falg=1;break;
}
}
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[maxn
2];
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<m;j++){
t=tbas+(a[i].s[j] == ‘Y’);t%=mod;
T=T
BAS+(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<m;j++){
t=tbas+(a[i].s[j]==‘N’);t%=mod;
T=T
BAS+(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<m;j++){
t=tbas+(a[i].s[j]==‘Y’);t%=mod;
T=T
BAS+(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<m;j++){
t=tbas+(a[i].s[j]==‘N’);t%=mod;
T=T
BAS+(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<m;i++)
if(a[ans].s[i]== ‘N’)printf(“Y”);
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<m;j++){
t=tbas+(a[i].s[j]==‘Y’);t%=mod;
T=T
BAS+(a[i].s[j]== ‘Y’);T%=MOD;
}
Insert(t,T);
t=0;T=0;
for(int j=0;j<m;j++){
t=tbas+(a[i].s[j]==‘N’);t%=mod;
T=T
BAS+(a[i].s[j]== ‘N’);T%=MOD;
}
Insert(t,T);
}
char r[510];
for(int i=0;i<m;i++)r[i]=‘N’;
while(1){
t=0,T=0;
for(int i=0;i<m;i++){
t=tbas+(r[i]==‘Y’);t%=mod;
T=T
BAS+(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;
}