T1

T2

T3

暴力

T4

我想到了的qwq,时间不够了,还是很简单,不上代码了.

T5密码*

  • 思路:
    • 用密文减去明文,可以得到:密文 - 明文 = 密钥 + 密文的前缀
    • 想要最短的密钥,那就使去掉的前缀尽可能的长。
    • 通过解密 nnn 对明文和密文,我们得到 nnn 个长短可能不相同的密钥,如果密钥存在,那么所有的的密钥都应该是最长的那个密钥的前缀
    • 最后再验证下最长的密钥是否合法
  • 代码:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
string a[N],b[N];
bool check(string x,string y,string z) {
    string tmp;
    for (int i=0;i<y.size();i++) {
        char k=(char)('A' + ( (x[i]+y[i]) %26 ));
        tmp+=k;
		x+=k;	//*
    }
    return tmp == z;
}
int main() {
	int n,t;
	scanf("%d",&t);
	while(t--) {
		scanf("%d",&n);
		//找出每种密钥 
		string c[N],s[N];
		for(int i=0;i<n;i++) {
			cin>>a[i]>>b[i];
			int len=a[i].size();
			for(int j=0;j<len;j++) {
				c[i]+='A'+(b[i][j]-a[i][j]+26)%26;
			}
//			cout<<c[i]<<endl;
			int mx=1;
			for(int j=0;j<len;j++) {		//正序枚举找到最大的后缀 
				if(c[i].substr(j)!=b[i].substr(0,len-j)) mx=j+1;
				else break;
			}
			s[i]=c[i].substr(0,mx);
		}
		int mx=0,id;
		for(int i=0;i<n;i++) {
			if(s[i].size()>mx) {
				id=i;
				mx=s[i].size();
			}
		}
		bool flag=true;
		if(!check(s[id],a[id],b[id])) flag=false;
		for(int i=0;i<n;i++) {
//			cout<<s[i]<<endl;
			if(i==id) continue;
			if(s[i]!=s[id].substr(0,s[i].size())||(!check(s[id],a[i],b[i]))) {
				flag=false;
			}
		}
		if(flag) cout<<s[id]<<endl;
		else cout<<"-"<<endl;
	}
	return 0;
}