7-10 妈妈再也不用担心我被拖库啦!
分数 25
退出全屏
作者 赵长乐
单位 西安工业大学
众所周知,互联网时代以来各大公司被“脱裤”的历史是一部五彩缤纷(误)的血泪史,给各大厂商造成了极大的经济损失。更为重要的是,由于有些用户在多个网站使用相同的用户名、密码,一旦一家网站被拖库,用户往往会遭受全方位的损失。为避免此情况,良心企业一般只在数据库中存储用户密码的哈希值——也就是根据特定规则产生的散列值,无法由此倒推出原密码。但这种方法也有一个缺点,即输入不同的密码有极小概率会得到一样的哈希值(我们称之为碰撞),从而被系统认定密码正确!现在你所在的公司采取如下方法产生密码字符串(长度至少为8,只包含大小写字母和数字)的哈希值:
- 不区分字母的大小写,沿用16进制A代表10,B代表11……的规律,将原字符串视为一串36进制的数字
- 将字符串平均划为4块,若无法平均划分,保证在前的分块不短于在后的分块,且长度差不超过1。如:长度26的字符串各分块长度为7、7、6、6,长度13的字符串各分块长度为4、3、3、3
- 将每块的数字加和,取其个位数,四块取出的四个36进制数字顺次连接,得到一个四位36进制数字,即为该密码字符串的哈希值。
然而由于这种方式过于睿智,使得碰撞的几率奇高,你的任务就是为公司防范风险,在碰撞发生的时候给予示警!
输入格式:
第一行一个整数N(N<1000),为操作的个数。
以下N行,每行一个字符、两个字符串(length<100),中间均以空格分隔。字符代表操作类型,两个字符串代表用户名和密码。
当字符为L时,代表以该用户名密码尝试登录;
当字符为R时,代表尝试注册这组用户名、密码,若注册成功则记录在案。
输出格式:
N行,对于每一个L(登录操作),若密码正确,则输出一行“Success!”;
若密码错误或用户不存在,则输出一行“Failed!”;
若密码错误但会通过哈希检测而被放行,则输出一行“Attention!”。
对于每一个R(注册操作),若已存在该用户名,则输出一行“Repeated!”;
否则注册成功,输出一行“Signed!”。
以上输出均不包括引号。
输入样例:
5
R IronMan 1234qwerasdf
R IronMan whejrdfs345
L IronMan 1234qwerasdf
L IronMan whejrdfs345
L IronMan 0km6trlhdcwc
输出样例:
Signed!
Repeated!
Success!
Failed!
Attention!
样例解释:
IronMan的密码为1234qwerasdf,会按照题设方法划分为【123】、【4qw】、【era】、【sdf】并求出哈希值6qfk,而0km6trlhdcwc按此法求出的哈希值也恰为6qfk,因此产生了哈希碰撞。
代码长度限制
16 KB
Java (javac)
时间限制
200 ms
内存限制
64 MB
其他编译器
时间限制
100 ms
内存限制
64 MB
栈限制
8192 KB
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<string,ll>mp;
map<string,string>mp1;
map<string,string>mp2;
char jz[36]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
ll bd(char y){
if(y>='0'&&y<='9')return 1;
if(y>='a'&&y<='z')return 2;
if(y>='A'&&y<='Z')return 3;
}
string hx(string x){
ll a=0,b=0,c=0,d=0;
ll l1=0,l2,l3,l4;
l1=l2=l3=l4=x.size()/4;
ll o=x.size();
if(o%4!=0){
l1++;
o--;
}
if(o%4!=0){
l2++;
o--;
}
if(o%4!=0){
l3++;
o--;
}
for(ll i=0;i<l1;i++){
if(bd(x[i])==1){
a+=x[i]-'0';
}
if(bd(x[i])==2){
a+=x[i]-'a'+10;
}
if(bd(x[i])==3){
a+=x[i]-'A'+10;
}
}
for(ll i=l1;i<l1+l2;i++){
if(bd(x[i])==1){
b+=x[i]-'0';
}
if(bd(x[i])==2){
b+=x[i]-'a'+10;
}
if(bd(x[i])==3){
b+=x[i]-'A'+10;
}
}
for(ll i=l1+l2;i<l1+l2+l3;i++){
if(bd(x[i])==1){
c+=x[i]-'0';
}
if(bd(x[i])==2){
c+=x[i]-'a'+10;
}
if(bd(x[i])==3){
c+=x[i]-'A'+10;
}
}
for(ll i=l1+l2+l3;i<x.size();i++){
if(bd(x[i])==1){
d+=x[i]-'0';
}
if(bd(x[i])==2){
d+=x[i]-'a'+10;
}
if(bd(x[i])==3){
d+=x[i]-'A'+10;
}
}
string ss="";
for(ll i=0;i<4;i++){
if(i==0){
ss+=jz[a%36];
}
if(i==1){
ss+=jz[b%36];
}
if(i==2){
ss+=jz[c%36];
}
if(i==3){
ss+=jz[d%36];
}
}
return ss;
}
int main(){
ll n;
cin>>n;
mp.clear();
while(n--){
char a;
string b,c;
cin>>a>>b>>c;
if(a=='R'){
if(!mp[b]){
cout<<"Signed!"<<endl;
mp[b]++;
mp1[b]=hx(c);
mp2[b]=c;
}else{
cout<<"Repeated!"<<endl;
}
}
if(a=='L'){
if(!mp[b]){
cout<<"Failed!"<<endl;
continue;
}
string ss=hx(c);
if(ss==mp1[b]){
if(mp2[b]!=c){
cout<<"Attention!"<<endl;
}else{
cout<<"Success!"<<endl;
}
}else{
cout<<"Failed!"<<endl;
}
}
}
return 0;
}