Official
E - 暗号変換装置とパスワード認証 / Cipher Conversion Device and Password Authentication Editorial
by
E - 暗号変換装置とパスワード認証 / Cipher Conversion Device and Password Authentication Editorial
by
physics0523
ひとまず、 \(B_i=0\) なる \(B_i\) を \(1\) とした暗号は、少なくとも \(0\) 人の認証が成功する辞書順最小のパスワードなので、それを暫定的な解とします。
エージェントの順番を \(N!\) 通り全て試すことを考えます。
エージェントの順番を固定した際、そのエージェントが見るパスワードが受ける変換を求めることができます。
この変換から、各エージェントが「正しい」とみなす元のパスワードを復元することができます。 このとき、元のパスワードに対して何人が正しいとみなすかも求めておくことができます。
このパスワードと \(B\) とを比較して、元のパスワードがありえるものであれば、問題文の基準に照らして「正しいとみなすエージェントの多い順」、同じであれば「辞書順最小」を採用することでこの問題に正解できます。
実装例 (C++):
#include<bits/stdc++.h>
using namespace std;
int main(){
int N,K,L;
cin >> N >> K >> L;
vector<int> B(L);
for(auto &nx : B){ cin >> nx; }
vector<vector<int>> T(N,vector<int>(L));
vector<vector<int>> A(N,vector<int>(K+1));
for(int i=0;i<N;i++){
for(int j=0;j<L;j++){cin >> T[i][j];}
for(int j=1;j<=K;j++){cin >> A[i][j];}
}
int rn=0;
vector<int> rp=B;
for(auto &nx : rp){
if(nx==0){nx=1;}
}
vector<int> agt;
for(int i=0;i<N;i++){agt.push_back(i);}
do{
vector<int> C(K+1);
for(int i=1;i<=K;i++){C[i]=i;}
map<vector<int>,int> mp;
for(auto &nx : agt){
vector<int> inv(K+1);
for(int i=1;i<=K;i++){ inv[C[i]]=i; }
vector<int> org(L);
for(int i=0;i<L;i++){
org[i]=inv[T[nx][i]];
}
mp[org]++;
vector<int> nC(K+1);
for(int i=1;i<=K;i++){ nC[i]=A[nx][C[i]]; }
C=nC;
}
for(auto &nx : mp){
bool ok=true;
for(int i=0;i<L;i++){
if(B[i]!=0 && B[i]!=nx.first[i]){ok=false; break;}
}
if(!ok){continue;}
if(rn<nx.second){
rn=nx.second;
rp=nx.first;
}
else if(rn==nx.second){
rp=min(rp,nx.first);
}
}
}while(next_permutation(agt.begin(),agt.end()));
cout << rn << "\n";
for(int i=0;i<L;i++){
if(i){cout << " ";}
cout << rp[i];
}cout << "\n";
return 0;
}
posted:
last update:
