【学习笔记】2021.10.16 - zhengru IOI 七连测 Day7

T1 字符串

Subtask 1 60pts

思路

  • 直接用 string 暴力模拟即可

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
string A,B,AU,BU;
int n,m,T,x;
long long maxsize;
inline bool doit(int xxx){
	if(maxsize>=xxx) return true;
	AU=A+B;
	BU=B+A;
	A=AU;
	B=BU;
	maxsize=A.length();
	if(maxsize>=xxx) return true;
	return false;
}
int main(){
	scanf("%d%d%d",&n,&m,&T);
	cin>>A>>B;
	while(T--){
		scanf("%d",&x);
		while(!doit(x));
		printf("%c\n",A[x-1]);
	}
	return 0;
}

正解

思路

  • 因为 \(A_0\)\(B_0\) 的长度不定,所以选择 \(A_1\)\(B_1\) 作为根元素来进行操作,因为它们的长度都是 n+m 。

  • 所以,我们先考虑求出每一个 x 在 \(A_{935}\) 中属于第几个元素,显然是 \(\left\lfloor \frac{x-1}{n+m} \right\rfloor + 1\) (就是上取整呀)。

  • 但是,怎么确定这个元素是 \(A_1\) 还是 \(B_1\) 呢?

  • 从 0 开始编号,此时上文的编号变成\(\left\lfloor \frac{x-1}{n+m} \right\rfloor\),记为 \(S\) ,不难证明如果 \((S)_2\) 中有奇数个 1 则为 \(B_1\) ,反之为 \(A_1\)

  • 这个很好证明,因为每次操作都是把当前序列取反一下再放在后面,也就是每次都会 \(\times 2\) ,所以每隔 \(2\) 的若干次方就会发生一次翻转,也就是说二进制表示下的 \(x\) 每多一个 1 就会发生翻转,所以这个元素属于什么只和二进制表示下的这个数中有多少个 1 的奇偶性有关。

  • 当然了,奇数偶数对应什么取决于你从哪里开始标号,从 0 开始自然就是这样了。

代码

还没写……

posted @ 2021-10-17 11:39  Binaries  阅读(42)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end