闲着没事写篇题解。
P3612 [USACO17JAN]Secret Cow Code S
题目大意:
一群闲着没事的奶牛研究密码,设初始密码为“ABC
”(题目给出的“COW”没那么好推算),那么:
1.1次操作后为“ABC
”+“CAB
”=“ABCCAB
”
2.2次操作后为“ABCCAB
”+“BABCCA
”=“ABCCABBABCCA
”
3.3次操作后为“ABCCABBABCCA
”+“AABCCABBABCC
”=“ABCCABBABCCAAABCCABBABCC
”
……
以此类推。
解题思路:
从推导过程中,我们可以发现,一次操作,可以分成以下几步:
1.将字符串复制;
2.将复制出的字符串的最后一个字母挪到第一个字符的位置;
3.连接两个字符串。
所以,我们设字符串为“ABC
”,求密码的第
8
8
8个字符的解题过程如下:
第
0
0
0次操作:
3
3
3位字符串;
第
1
1
1次操作:
6
6
6位字符串;
第
2
2
2次操作:
12
12
12位字符串;
6
≤
8
≤
12
6\le8\le12
6≤8≤12,
8
−
6
=
2
8-6=2
8−6=2,所以,我们可以知道,这个要求的字符在第二次操作中新增字符串的第2位,根据规律,我们得出,这个字符是第
2
2
2次操作前,第
1
1
1次操作后的第
1
1
1位。在重复以上操作,我们发现
1
≤
3
1\le3
1≤3,那么,这个字符就是初始字符串中的第
1
1
1位,为A
。
代码实现:
理论存在,实践开始。
根据上边的解题步骤,我们列出以下代码:
#include<bits/stdc++.h>
using namespace std;
char a[35];
int m,n,l;
char dg(int l,int r,int L,int R,int p){
if (p<=m){
return a[p];
}
if (p<=r){
return dg(l,r/2,r/2+1,r,p);
}
else{
long long rk=p-L+1;
if (rk==1){
return dg(l,r/2,r/2+1,r,r);
}
else{
return dg(l,r/2,r/2+1,r,rk-1);
}
}
}
int main(){
cin>>a+1>>n;
m=strlen(a+1);
l=m;
while (l<n){
l*=2;
}
cout<<dg(1,l/2,l/2+1,l,n);
}
提交结果:
只有50分,本蒟蒻反复检查代码没发现问题,后来瞟了一眼数据范围,发现
int
小了,于是把所有的int
换成longlong
之后,成了这样:
#include<bits/stdc++.h>
using namespace std;
char a[35];
long long m,n,l;
char dg(long long l,long long r,long long L,long long R,long long p){//不开long long见祖宗(确信)
if (p<=m){
return a[p];
}//如果在初始字符串内,返回第p个字符
if (p<=r){
return dg(l,r/2,r/2+1,r,p);
}
else{
long long rk=p-L+1;
if (rk==1){
return dg(l,r/2,r/2+1,r,r);
}
else{
return dg(l,r/2,r/2+1,r,rk-1);
}
}
}
int main(){
cin>>a+1>>n;
m=strlen(a+1);
l=m;
while (l<n){
l*=2;
}//保证长度足够
cout<<dg(1,l/2,l/2+1,l,n);//递归
}
AC,完结撒花
祝你AC!