链接:https://ac.nowcoder.com/acm/contest/329/J
来源:牛客网
题目描述
经过了训练、资金等多方面的准备,处女座终于可以去比赛了!比赛采用codeforces赛制,也就意味着可以插人。现在有一道字符串的题目,处女座在room里看到一个用hash做的,于是决定把它hack掉。这个人的核心代码如下:
const int mod=9983;mul[0]=p;mul[1]=q;mul[2]=r;for (int i=0;i<26;i++)in_dex[i]=i*t+t;
int get_hash(char* s)//下标从1开始{int ans=0,len=strlen(s+1);for (int i=1;i<=len;i++)ans=(ans*mul[i%3] + in_dex[s[i]-'a'])%mod;return ans;}
现在处女座给你他想用来hack的第一个字符串 s1s1,和常数p,q,r,t,请你帮他找出第二个字符串s2s2,使得get_hash(s1)=get_hash(s2)get_hash(s1)=get_hash(s2)。
输入描述:
输入数据共两行,第一行为四个整数p,q,r,t,表示代码里的常数。
第二行为一个整数T,表示数据组数。
接下来一行,每行一个仅由小写字母构成的字符串s1s1,表示处女座想用来hack的字符串。
输出描述:
输出一行一个和s1s1不同的仅由小写字母构成的字符串s2s2,使得get_hash(s1)=get_hash(s2)get_hash(s1)=get_hash(s2)且|s2|≤20,000|s2|≤20,000。
备注:
100≤p,q,r≤999100≤p,q,r≤999
2≤t≤9992≤t≤999且t是素数
1≤|s1|≤10,0001≤|s1|≤10,000
1≤T≤1,0001≤T≤1,000
数据保证p,q,r,t和s1s1均为随机生成
这套题不知不觉得就结束了,祝各位大佬们看到能愉快的AK本场比赛,同时也祝处女座早日能找到真正能够两心欢悦的小姐姐,前途似锦。
注:本次比赛中出现的所有图均为真实聊天截图,均为处女座本人所述,无任何PS部分。
思路:
突破口在题目中的mod,
mod=9983,
显然mod是很小的,我们分析如果长度为4的串,有26*26*26*26个,
然后暴力跑数据的时候发现枚举长度为4的所有字符串可以得到hash值为0~9983的至少两个。
那么我们就可以预处理枚举出长度为4个的所有字符串后,把每一个字符串加入到对应hash值的数组中,
然后当询问给出一个字符串的时候,会对应哈希值的数组中找到任意一个不等于当前字符串的string即可。
细节见AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;} inline void getInt(int* p); const int maxn=1000010; const int inf=0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ const int mod=9983; int p,q,r,t; int mul[maxn]; int in_dex[maxn]; int get_hash(string s)//下标从1开始 { int ans=0,len=s.size(); for (int i=0;i<len;i++) ans=(ans*mul[(i+1)%3] + in_dex[s[i]-'a'])%mod; return ans; // int ans=0,len=s.size(); // for (int i=0;i<len;i++) // ans=(ans*mul[i%3] + in_dex[s[i]-'a'])%mod; // return ans; } string s; std::vector<string> a[maxn]; int main() { cin>>p>>q>>r>>t; mul[0]=p;mul[1]=q;mul[2]=r; for (int i=0;i<26;i++)in_dex[i]=i*t+t; // pre // key for(int i=0;i<26;i++) for(int j=0;j<26;j++) for(int k=0;k<26;k++) for(int l=0;l<26;l++) { string s=""; s+=char(i+'a'); s+=char(j+'a'); s+=char(k+'a'); s+=char(l+'a'); a[get_hash(s)].pb(s); } // main int T; cin>>T; while(T--) { cin>>s; int sum=get_hash(s); for(int i=0;i<a[sum].size();i++) if(a[sum][i]!=s) { cout<<a[sum][i]<<endl;break; } } return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == '\n'); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }