题解:P11858 [CCC 2025 Senior] 破译 / Cryptogram Cracking Club

· · 题解

思路

,展开后s长度甚至可以达到$5*10^ {16}$, _**所以明显这题需通过取模来获取答案**_ 可以考虑先跑一遍 $s'$ ,将 $s$ 的长度 $lon$算出来; 如果 $lon$已经比 $c$还要大的话,直接输出即可;不然就直接 $c\bmod=lon$,然后再跑一遍 $s'$ 即可。 --- # **代码** 1. 首先是对 $s'$ 中数字的取出,代码如下( $ans$ 储存的是 $s'$ 长度) ```cpp s=s+" ",c++;//在s'后面加一个空格,不然最后一个数字会取不到;c++是因为s[0]是第一个字符 long long i=0,len=s.size(),number=0;//不开longlong见祖宗 string zm;//用于存储当前数字所对应的字母 while(i<=len) { if(s[i]>='0' && s[i]<='9') number=number*10+s[i]-'0';//是数字取出就行 else {//不是数字 ans+=number; if(ans>=c){//如果已经达到了c,直接输出 cout<<zm; return 0; } zm=s[i]; number=0; } i++; } ``` 2. 在完成数字的取出后,如果代码还没结束,说明字符串长度 $ans>c$ ;这时候如果一直往后搜索肯定不行的,取模可以解决一切 ```cpp c%=ans; ``` 取模之后, $c<ans$ 是必然的,所以再次进行上面同样的操作必然可以找出答案 所以,直接重复上面的操作(一摸一样的,注意重新初始化哦)就可以了 但是,有一个小细节,如果没有注意到就会只有6分,如果 $c$ 是 $ans$ 的倍数,那么 $c%ans$ 就会是 $0$ ,而第 $0$ 个数是取不到的!所以要特判! ```cpp if(c==0) c=ans; ``` # **完整代码** ```cpp #include<bits/stdc++.h> using namespace std; string s; long long c,ans=0; int main() { cin>>s>>c; s=s+" ",c++; long long i=0,len=s.size(),number=0; string zm; while(i<=len) { if(s[i]>='0' && s[i]<='9') number=number*10+s[i]-'0'; else { ans+=number; if(ans>=c){ cout<<zm; return 0; } zm=s[i]; number=0; } i++; } c=c%ans; //重开 if(c==0) c=ans; i=0,number=0,ans=0; zm=""; while(i<=len) { if(s[i]>='0' && s[i]<='9') number=number*10+s[i]-'0'; else { ans+=number; if(ans>=c){ cout<<zm; return 0; } zm=s[i]; number=0; } i++; } return 0; } ```