题解:P11858 [CCC 2025 Senior] 破译 / Cryptogram Cracking Club
qrz0226
·
·
题解
思路
,展开后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;
}
```