P3612 [USACO17JAN]Secret Cow Code S
题目链接 https://www.luogu.com.cn/problem/P3612
思路是看的dalao的。。。代码是模仿dalao的。。。Um...
光看懂题目我就用了好长时间啊。。。但是是一道很有意思的题目!
首先看到数据范围:n<=1018,那么显而易见,分治欢迎您!
梳理题意:
给定一个字符串,每次将其最后一个字符移到最前方,形成的新串接到原串后作为下一次操作的字符串,现询问第n个位置的字符。
解析题目:
拿cow距离,新串(cowwco)的前一半字符(cow)和上一个串(cow)完全一样,后一半字符(wco)的第一个字符('w'co)是前一半字符的最后一个(co'w'),剩余的字符(co)是前一半字符除了最后一个字符的所有('co'w)。所有的新串以此类推。
大致思路:
此题最重要的是找到题目规律并推出递归的式子。
拿n=8举例:先求出当前刚好包括n位置的串长,那么第八个字符出现在旋转两次后的字符串(即第三个字符串)中,则n=8位置的字符在旋转一次后的字符串(上一个串,即第二个串)中的位置为n=n-1-L/2。
右边的n表示字符在最新串(第三个串)中的位置,左边的n为字符在上一个串(第二个串)中的位置。
通过上式可以推出:第三个串中n=8时的字符,在第二个串中的位置为n=1。
当n<num时,表示已经在初始字符串中找到在无限字符串中n所表示的字符。
放AC代码(好短!(bushi)
1 #include <bits/stdc++.h> 2 using namespace std; 3 string s; 4 long long n,num,i; 5 int main() 6 { 7 cin>>s>>n; 8 num=s.length(); 9 while(num<n) 10 { 11 i=num; 12 while(n>i) i*=2;//求出当前刚好包括n位置的串长 13 i=i/2;//得到当前串的一半长 14 n-=(i+1); 15 if(n==0) n=i; 16 } 17 cout<<s[n-1]; 18 }