https://www.luogu.org/problem/P1092
题意: 给你三个n长度的字符串, 每个字母代表的值为 0 ……n-1, 要使字符串被替代以后得到的等式成立, 请输出n个数字 分别表示A B C …… 所代表的值
有个方法是暴力枚举 加 剪枝, 但是具体做法有点取巧
首先记录三个字符串出现的字符对应- 'A' 后的下标(从前到后, 再用一个next1数组(从后到前记录出现下标的次序,
dfs 暴力从n-1 ……0 枚举每个下标可能出现的值, 再加上剪枝(第一位相加不会超过n 且 每个前两位相加得到第三位的值或者第三位的值减一)
这个做法 默认了所有的字母都会出现在三个字符串中, 还用了一个 玄学的next1数组, 结果是能过 但是确实有些玄学
#include <bits/stdc++.h> using namespace std; #define _for(i,a,b) for(int i = (a); i < (b); i++) #define _rep(i,a,b) for(int i = (a); i <= (b); i++) #define _per(i,a,b) for(int i = (a); i > (b); i--) #define ll long long const int N = 27; int n, a[N],b[N],c[N],num[N],next1[N],cnt = 1; bool used[N]; string s[4]; bool flag = true; bool canprune() {// prune if(num[a[1]]+num[b[1]] >= n) return true; _per(i,n,0) { int A = num[a[i]], B = num[b[i]], C = num[c[i]]; if(A == -1 || B == -1 || C == -1 || (A+B)%n==C || (A+B+1)%n==C) continue; return true; } return false; } bool cmp2(){// 確認 int x = 0; for(int i = n; i > 0; i--) { int A = num[a[i]], B = num[b[i]], C = num[c[i]]; if((A+B+x)%n != C) return false; x = (A+B+x >= n); } return true; } void print1(){ _rep(i,1,n) cout << num[i] <<(i==n ? " " : " "); exit(0);//必须有 不然 8、9两个点 会 TLE } void dfs(int x){ if(canprune()) { return;} if(x == n+1){ if(cmp2()) print1(); return; } for(int i = n; i > 0; i--) {// 倒着赋值 if(!used[i]){ used[i] = true; num[next1[x]] = i-1; dfs(x+1); used[i] = false; num[next1[x]] = -1; } }return; } void getnext1(int x){//根据出现次序构成 next1 数组, 能快些(50->70 if(!used[x])//默认所有字母都会出现 { next1[cnt++] = x; used[x] = true; }return; } void solve(){ cin >> n; string s1, s2, s3; cin >> s1 >> s2 >> s3; //cout << "s1 = " << s1 << " s2 = " << s2 << " s3 = " << s3 << endl; memset(num, -1, sizeof(num)); //_rep(i,1,26) used[i] = false; _rep(i,1,n) { a[i] = s1[i-1]-'A'+1; b[i] = s2[i-1]-'A'+1; c[i] = s3[i-1]-'A'+1; } for(int i = n; i > 0; i--) {//倒过来 getnext1(a[i]);//顺序不可乱 getnext1(b[i]); getnext1(c[i]); } _rep(i,1,26) used[i] = false; dfs(1); } int main(){ ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); //freopen("output.txt", "w", stdout); solve(); return 0; }
test(9)
20
NLHFIEASBRQJOGKMDPCT
NQGPSIIGKDMFDCBFMQSO
PNKNTOLHEIJHFGJKHJGG
18 14 0 9 15 17 7 13 12 16 1 10 4 2 8 5 11 3 6 19
test(8)
18
FQAGNMBECLPOJDHIKR
ADQGABEHFDQADOKPML
LOCOLJFGIRMGJKQCDH
13 12 4 0 8 3 5 15 7 1 11 16 6 2 10 14 9 17
正解:高斯消元