正确答案

正确答案

题目描述

小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.

来源

八校长乐day1

solution:

看到m有500,n有30000,时间复杂度O(n^2)肯定是不行的,只能是O(nm)的。这就意味着要查找一种答案出现了几次不能枚举每一个人,得存下来,最多花费O(lg n)的时间查询。于是需要给每一个答案进行编号,很自然地想到了Hash。最多会有n个答案,不能直接用数组存,因为想要开的下,p就得比较小,由于生日悖论,会有很多冲突,且是单Hash,很容易出错,这太不靠谱。其实p很大的话,实测证明单Hash也可以,但还是开不下数组的,还不如双Hash保险一点。一个比较好的方法是将每一对Hash值捆在一起,排序,查找时候二分一下就好了,查询时间复杂度O(lg n),可以的。当然,像我这样的C++选手是不愿意这样写的,我很懒的。可以用set和自带的二分,这样会方便的多,然而最方便的肯定是map,直接当数组用,看似10^18次的数组,实际上只有O(n)的空间,神器啊!不过map是用红黑树写的,所以时间复杂度还是O(lg n),且常数因子大,速度会慢一些。好在这道题目并不怕TLE,可以放心的用。这样做法就很简单了,枚举每一个答案,计算它的Hash值,得到它出现的次数,判断是否等于p,如果是,再将它取反(N变Y,Y变N),计算Hash值,判断是否等于q,如果也是,则将这个原串与答案比较,取字典序最小的。当心p、q可以是0,要特殊处理,特别是p=q=0的时候,直接暴力枚举就好了,O(n)的。下面是代码,用了STL还是很长……

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
ll read(){
    ll ans=0;
    char ch=getchar(),last=' ';
    while(ch>'9'||ch<'0'){
        last=ch;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0'){
        ans=ans*10+ch-'0';
        ch=getchar();
    }
    if(last=='-')
        ans=-ans;
    return ans;
}
map<ll,map<ll,int> > a;
int n,m,p,q;
ll x,y,ans,xx,yy,p1,p2;
char st[30005][505],ac[505];
bool flag;
bool ok(char* a,char* b){
    for(int i=0;i<m;i++)
        if(a[i]!=b[i])
            return a[i]<b[i];
    return false;
}
int main(){
    p1=(ll)1000000007;
    p2=(ll)1000000003;
    n=read();
    m=read();
    p=read();
    q=read();
    for(int i=1;i<=n;i++){
        scanf("%s",st[i]);
        x=y=0;
        for(int j=0;j<m;j++){
            x=(x+x)%p1;
            y=(y+y)%p2;
            if(st[i][j]=='Y'){
                x=(x+(ll)1)%p1;
                y=(y+(ll)1)%p2;
            }
        }
        a[x][y]++;
    }
    if(p==0&&q==0){
        for(int i=0;i<m;i++)
            ac[i]='N';
        ac[m-1]='Y';
        while(1){
            x=y=0;
            for(int j=0;j<m;j++){
                x=(x+x)%p1;
                y=(y+y)%p2;
                if(ac[j]=='Y'){
                    x=(x+(ll)1)%p1;
                    y=(y+(ll)1)%p2;
                }
            }
            xx=yy=0;
            for(int j=0;j<m;j++){
                xx=(xx+xx)%p1;
                yy=(yy+yy)%p2;
                if(ac[j]=='N'){
                    xx=(xx+(ll)1)%p1;
                    yy=(yy+(ll)1)%p2;
                }
            }
            if(a[x][y]==0&&a[xx][yy]==0){
                flag=true;
                break;
            }
            int k=-1;
            for(int j=m-1;j>=0;j--)
                if(ac[j]=='N'){
                    k=j;
                    break;
                }
            ac[k]='Y';
            for(int j=k+1;j<m;j++)
                ac[j]='N';  
        }
        if(flag){
            for(int j=0;j<m;j++)
                printf("%c",ac[j]);
            printf("\n");
        }
        else
            printf("-1\n");
        return 0;
    }
    if(p==0){
        for(int i=1;i<=n;i++){
            x=y=0;
            for(int j=0;j<m;j++){
                x=(x+x)%p1;
                y=(y+y)%p2;
                if(st[i][j]=='Y'){
                    x=(x+1)%p1;
                    y=(y+1)%p2;
                }
            }
            xx=yy=0;
            for(int j=0;j<m;j++){
                xx=(xx+xx)%p1;
                yy=(yy+yy)%p2;
                if(st[i][j]=='N'){
                    xx=(xx+1)%p1;
                    yy=(yy+1)%p2;
                }
            }
            if(a[x][y]==q&&a[xx][yy]==p){
                ans++;
                if(ans==1||ok(ac,st[i]))
                    for(int j=0;j<m;j++)
                        ac[j]=st[i][j];
            }
        }
        if(ans){
            for(int j=0;j<m;j++)
                printf("%c",ac[j]=='Y'?'N':'Y');
            printf("\n");
        }
        return 0;
    }
    if(q==0){
        for(int i=1;i<=n;i++){
            x=y=0;
            for(int j=0;j<m;j++){
                x=(x+x)%p1;
                y=(y+y)%p2;
                if(st[i][j]=='Y'){
                    x=(x+1)%p1;
                    y=(y+1)%p2;
                }
            }
            xx=yy=0;
            for(int j=0;j<m;j++){
                xx=(xx+xx)%p1;
                yy=(yy+yy)%p2;
                if(st[i][j]=='N'){
                    xx=(xx+1)%p1;
                    yy=(yy+1)%p2;
                }
            }
            if(a[x][y]==p&&a[xx][yy]==q){
                ans++;
                if(ans==1||ok(st[i],ac))
                    for(int j=0;j<m;j++)
                        ac[j]=st[i][j];
            }
        }
        if(ans){
            for(int j=0;j<m;j++)
                printf("%c",ac[j]);
            printf("\n");
        }
        return 0;
    }
    for(int i=1;i<=n;i++){
        x=y=0;
        for(int j=0;j<m;j++){
            x=(x+x)%p1;
            y=(y+y)%p2;
            if(st[i][j]=='Y'){
                x=(x+1)%p1;
                y=(y+1)%p2;
            }
        }
        xx=yy=0;
        for(int j=0;j<m;j++){
            xx=(xx+xx)%p1;
            yy=(yy+yy)%p2;
            if(st[i][j]=='N'){
                xx=(xx+1)%p1;
                yy=(yy+1)%p2;
            }
        }
        if(a[x][y]==p&&a[xx][yy]==q){
            ans++;
            if(ans==1||ok(st[i],ac))
                for(int j=0;j<m;j++)
                    ac[j]=st[i][j];
        }
    }
    if(ans){
        for(int j=0;j<m;j++)
            printf("%c",ac[j]);
        printf("\n");
    }
    else
        printf("-1\n");
    return 0;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38601996/article/details/75143404
个人分类: 字符串Hash
想对作者说点什么? 我来说一句

SSD4 exam2 答案 保证正确

2010年01月16日 1.43MB 下载

SSD3 exercise5 答案 保证正确

2010年01月16日 7KB 下载

SSD3 exercise3 答案 保证正确

2010年01月16日 3KB 下载

SSD4 exam1 答案 保证正确

2010年01月16日 52KB 下载

SSD3 exercise2 答案 保证正确

2010年01月16日 63KB 下载

没有更多推荐了,返回首页

不良信息举报

正确答案

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭