正确答案
正确答案
题目描述
小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还是很长……
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<cstring> 7 #include<map> 8 using namespace std; 9 typedef long long ll; 10 ll read(){ 11 ll ans=0; 12 char ch=getchar(),last=' '; 13 while(ch>'9'||ch<'0'){ 14 last=ch; 15 ch=getchar(); 16 } 17 while(ch<='9'&&ch>='0'){ 18 ans=ans*10+ch-'0'; 19 ch=getchar(); 20 } 21 if(last=='-') 22 ans=-ans; 23 return ans; 24 } 25 map<ll,map<ll,int> > a; 26 int n,m,p,q; 27 ll x,y,ans,xx,yy,p1,p2; 28 char st[30005][505],ac[505]; 29 bool flag; 30 bool ok(char* a,char* b){ 31 for(int i=0;i<m;i++) 32 if(a[i]!=b[i]) 33 return a[i]<b[i]; 34 return false; 35 } 36 int main(){ 37 p1=(ll)1000000007; 38 p2=(ll)1000000003; 39 n=read(); 40 m=read(); 41 p=read(); 42 q=read(); 43 for(int i=1;i<=n;i++){ 44 scanf("%s",st[i]); 45 x=y=0; 46 for(int j=0;j<m;j++){ 47 x=(x+x)%p1; 48 y=(y+y)%p2; 49 if(st[i][j]=='Y'){ 50 x=(x+(ll)1)%p1; 51 y=(y+(ll)1)%p2; 52 } 53 } 54 a[x][y]++; 55 } 56 if(p==0&&q==0){ 57 for(int i=0;i<m;i++) 58 ac[i]='N'; 59 ac[m-1]='Y'; 60 while(1){ 61 x=y=0; 62 for(int j=0;j<m;j++){ 63 x=(x+x)%p1; 64 y=(y+y)%p2; 65 if(ac[j]=='Y'){ 66 x=(x+(ll)1)%p1; 67 y=(y+(ll)1)%p2; 68 } 69 } 70 xx=yy=0; 71 for(int j=0;j<m;j++){ 72 xx=(xx+xx)%p1; 73 yy=(yy+yy)%p2; 74 if(ac[j]=='N'){ 75 xx=(xx+(ll)1)%p1; 76 yy=(yy+(ll)1)%p2; 77 } 78 } 79 if(a[x][y]==0&&a[xx][yy]==0){ 80 flag=true; 81 break; 82 } 83 int k=-1; 84 for(int j=m-1;j>=0;j--) 85 if(ac[j]=='N'){ 86 k=j; 87 break; 88 } 89 ac[k]='Y'; 90 for(int j=k+1;j<m;j++) 91 ac[j]='N'; 92 } 93 if(flag){ 94 for(int j=0;j<m;j++) 95 printf("%c",ac[j]); 96 printf("\n"); 97 } 98 else 99 printf("-1\n"); 100 return 0; 101 } 102 if(p==0){ 103 for(int i=1;i<=n;i++){ 104 x=y=0; 105 for(int j=0;j<m;j++){ 106 x=(x+x)%p1; 107 y=(y+y)%p2; 108 if(st[i][j]=='Y'){ 109 x=(x+1)%p1; 110 y=(y+1)%p2; 111 } 112 } 113 xx=yy=0; 114 for(int j=0;j<m;j++){ 115 xx=(xx+xx)%p1; 116 yy=(yy+yy)%p2; 117 if(st[i][j]=='N'){ 118 xx=(xx+1)%p1; 119 yy=(yy+1)%p2; 120 } 121 } 122 if(a[x][y]==q&&a[xx][yy]==p){ 123 ans++; 124 if(ans==1||ok(ac,st[i])) 125 for(int j=0;j<m;j++) 126 ac[j]=st[i][j]; 127 } 128 } 129 if(ans){ 130 for(int j=0;j<m;j++) 131 printf("%c",ac[j]=='Y'?'N':'Y'); 132 printf("\n"); 133 } 134 return 0; 135 } 136 if(q==0){ 137 for(int i=1;i<=n;i++){ 138 x=y=0; 139 for(int j=0;j<m;j++){ 140 x=(x+x)%p1; 141 y=(y+y)%p2; 142 if(st[i][j]=='Y'){ 143 x=(x+1)%p1; 144 y=(y+1)%p2; 145 } 146 } 147 xx=yy=0; 148 for(int j=0;j<m;j++){ 149 xx=(xx+xx)%p1; 150 yy=(yy+yy)%p2; 151 if(st[i][j]=='N'){ 152 xx=(xx+1)%p1; 153 yy=(yy+1)%p2; 154 } 155 } 156 if(a[x][y]==p&&a[xx][yy]==q){ 157 ans++; 158 if(ans==1||ok(st[i],ac)) 159 for(int j=0;j<m;j++) 160 ac[j]=st[i][j]; 161 } 162 } 163 if(ans){ 164 for(int j=0;j<m;j++) 165 printf("%c",ac[j]); 166 printf("\n"); 167 } 168 return 0; 169 } 170 for(int i=1;i<=n;i++){ 171 x=y=0; 172 for(int j=0;j<m;j++){ 173 x=(x+x)%p1; 174 y=(y+y)%p2; 175 if(st[i][j]=='Y'){ 176 x=(x+1)%p1; 177 y=(y+1)%p2; 178 } 179 } 180 xx=yy=0; 181 for(int j=0;j<m;j++){ 182 xx=(xx+xx)%p1; 183 yy=(yy+yy)%p2; 184 if(st[i][j]=='N'){ 185 xx=(xx+1)%p1; 186 yy=(yy+1)%p2; 187 } 188 } 189 if(a[x][y]==p&&a[xx][yy]==q){ 190 ans++; 191 if(ans==1||ok(st[i],ac)) 192 for(int j=0;j<m;j++) 193 ac[j]=st[i][j]; 194 } 195 } 196 if(ans){ 197 for(int j=0;j<m;j++) 198 printf("%c",ac[j]); 199 printf("\n"); 200 } 201 else 202 printf("-1\n"); 203 return 0; 204 }