agc020D - Min Max Repetition

题目大意


题解

网上的做法好像都要二分?

显然可以反向构造,如果A<B那就把AB交换把CD在序列上对称,然后最后答案把AB互换即可

假设找到最小的s满足(B+1)s>=A,然后显然是从后往前删A,并且不能有s个B连在一起

写法应该有很多,这里讲一种比较舒服的写法

首先特判掉只删末尾的情况,观察一下发现,最终的串是由AAABAAAB...BBBABBB之类的串构成的,即若干s个A1个B的串,加上若干s个B一个A的串的反转(末尾不一定完整)

那么先把后面的ABBB这种的数量算出来,每有一个前面就会少一个A,然后除一下就可以算出分解线了

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int T,n,s,s2,s3,i,j,k,l,A,B,C,D;
char ans[101];
bool bz;

void swap(int &x,int &y) {int z=x;x=y;y=z;}

int main()
{
	#ifdef file
	freopen("agc020D.in","r",stdin);
	#endif
	
	scanf("%d",&T);
	for (;T;--T)
	{
		scanf("%d%d%d%d",&A,&B,&C,&D),bz=0;
		if (A<B) swap(A,B),C=(A+B)-C+1,D=(A+B)-D+1,swap(C,D),bz=1;
		s=ceil((double)A/(B+1));
		
		if (A>=B*s)
		{
			fo(i,C,D)
			ans[i-C+1]=(!(i%(s+1)))?'B':'A';
		}
		else
		{
			s2=(B*s-A)/(s*s-1);
			s3=(A-s2)+(A-s2)/s;
			fo(i,C,D)
			if (i<=s3)
			ans[i-C+1]=(!(i%(s+1)))?'B':'A';
			else
			ans[i-C+1]=(!(((A+B)-i+1)%(s+1)))?'A':'B';
		}
		
		if (!bz)
		{
			fo(i,1,D-C+1) putchar(ans[i]);
			putchar('\n');
		}
		else
		{
			fd(i,D-C+1,1) putchar(ans[i]=='A'?'B':'A');
			putchar('\n');
		}
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-09-29 12:12  gmh77  阅读(121)  评论(0编辑  收藏  举报