牛子题
优先满足第二个条件,长度是 \(\lceil \frac{max(A,B)}{min(A,B)+1}\rceil\) ,那么现在要满足字典序最小,发现先填 \(A..ABA..ABA..AB..\) ,中途可能 \(B>>A\) 就填不满 ,就要改变策略,变成 \(B..BAB..BA...\) 这样子的,但是注意可能 \(B\) 有余数,那我肯定优先把有余数个 \(B\) ,这样子肯定字典序小一点,然后二分两种方式的分界点, \(check\) 的话直接判断 \(shengB\times len \leq shengA\) 就行了
关于 \(check\) 的写法,为什么这样是对的?先考虑普通情况,正确性显然,但是如果 \(shengB \times len = shengA\) ,说明没有余数,那就是先填 \(A\) ,那万一之前最后一个也是 \(A\) , 就会寄掉,但是其实我们可以调整一下,把最后的 \(B\) 调整一个过来,把第二段的 \(A\) 给第一段,就是合法的了,本质上是分界点向右移动了,所以对于这种情况要返回 \(true\) 才行,不然答案会错
然后注意二分要像下面的代码那么写才不会错
#include<bits/stdc++.h>
#define il inline
#define int long long
using namespace std;
il int read(){
char c;int x=0,f=0;
while(!isdigit(c=getchar()))f|=(c=='-');
while(isdigit(c))x=(x*10)+(c^48),c=getchar();
return f?-x:x;
}
int A,B,C,D,len;
il bool check(int fjd){
int shengA=A-fjd/(len+1)*len-fjd%(len+1),shengB=B-fjd/(len+1);
return shengA*len>=shengB;
}
signed main(){
int t=read();
while(t--){
A=read(),B=read(),C=read(),D=read();
len=ceil(max(A,B)*1.0/(min(A,B)+1));
int lt=0,rt=A+B+1,pos=0;
while(lt<rt){
int mid=(lt+rt)>>1;
if(check(mid))lt=mid+1;
else rt=mid;
}
pos=lt;
int shengA=A-pos/(len+1)*len-pos%(len+1),shengB=B-pos/(len+1);
int fstA=shengB-shengA*len+pos+1;
for(int i=C;i<=D;i++){
if(i<=pos){
if(i%(len+1))putchar('A');
else putchar('B');
}
else if(i>pos&&i<fstA)putchar('B');
else if(i>=fstA){
if((i-fstA+1)%(len+1)==1)putchar('A');
else putchar('B');
}
}
puts("");
}
return 0;
}
标签:..,int,Max,shengB,len,read,shengA,Repetition,AGC020D
From: https://www.cnblogs.com/blueparrot/p/17904943.html