正确答案

正确答案

题目描述

小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
上一篇都市环游
下一篇帮助Bsny(乱搞做法)
想对作者说点什么? 我来说一句

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

关闭
关闭
关闭