CF720E Cipher 题解
CF720E Cipher 题解
知识点
进制,模拟,贪心。
分析
发现我们想要确定一位数时,只有两种方法:
- 该位数字自己加 \(1\),从变化顺序可以看出它是哪一位。
- 该位数字加 \(1\),导致高位数字出现变化,看出它现在变成了 \(0\)。这种情况包括整个数字达到了 \(n+1\) 位的情况。
那么我们从高位开始遍历,记一个答案为 \(ans\),最小进位且变化的值为 \(len\),初始时设为 \(1\)。
每次想要确定这一位数是否可行,就要和别的数进行比较,直到能够把两个数区分开。假设此位为 \(c\),比较的为 \(j\),那么比较的方法有两种:
- 循环串最长公共前缀长度 \(+1\)。
- 如果 \(j\) 能够引起高位进位,且进位能够看出来。
我们对于同一个 \(j\),在这两种中取 \(\min\),得到这一位的答案 \(lim\),最后再整个答案 \(ans\) 中取 \(\max\)。
当我们从高一位到低一位的时候,我们需要更新 \(ans,len\),不过根据定义,也不难实现。
时间复杂度 \(O(nw^2),w=10\)。
代码
constexpr int N(18+10);
char s[N],t[N];
int Cas,n;
ll ans,len;
int Cmain() {
/*DE("Input");*/
I(n),scanf("%s",s),ans=0,len=1;
/*DE("Solve");*/
FOR(i,0,n-1) {
const int c(s[i]^48);
scanf("%s",t),ans=ans*10-c;
FOR(j,0,9)if(j!=c) {
ll lim(len*10-max(j,c)); //上一位进位带来的影响
FOR(k,0,min(lim-1,9ll))if(t[(c+k)%10]!=t[(j+k)%10]&&(lim=k,true))break;
tomax(ans,lim);
}
len=len*10-c;
FOR(j,1,9)if(t[c]!=t[(c+j)%10]&&(tomin(len,(ll)j),true))break;
}
/*DE("Output");*/
O(ans,'\n');
return 0;
}
signed main() {
#ifdef Plus_Cat
freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
#endif
for(I(Cas); Cas; --Cas)Cmain();
return 0;
}

浙公网安备 33010602011771号