題目
給你一個n(n<=2e5),一個A數組,一個B數組(1<=Ai,Bi<=1e12)
你可以對A數組進行兩種操作,
①反轉A數組,記爲R操作
②對A數組做前綴和,即[A1,A2,...]->[A1,A1+A2,...],記爲P操作
問A能否變成B,如果不能輸出IMPOSSIBLE
否則,
若P操作超過2e5次,輸出BIG,以及P操作的次數
P操作沒超過2e5次,輸出SMALL,R和P的操作總數,以及R和P的操作序列
思路來源
http://www.360doc.com/content/20/0604/21/13328254_916532267.shtml
qls代碼
題解
考慮到一個長度爲3的1 1 1數組,做前綴和n次,第二項是O(n)級的,第三項是O(n^2)級的,
這樣大致1e6次操作就能到1e12了,所以n>3的可暴力
暴力的時候,發現a到b也不好做,
考慮如何b逆推回a,因爲做完前綴和之後的數組肯定是增序的,這樣就可以差分回去了
先檢查a和b是否完全一致,a和b的逆序是否完全一致,一致直接返回
否則,如果b是嚴格增序(因爲沒有0)或降序的,說明經歷了一次前綴和或前綴和加一次反轉
那麼如果是增序的,就差分一次,再判斷
n=1顯然可以特判,考慮n=2怎麼做
n=2,也在每步之前,判一下a和b是否完全一致,a和b的逆序是否完全一致,一致直接返回,
否則,不妨設b[1]<b[2](大於先R一次),考慮其與min(a[1],a[2])和max(a[1],a[2])的關係,
若b[1]<min(a[1],a[2]),顯然無法再通過差分得到
若b[1]=min(a[1],a[2]),說明已經對齊,此時b[2]如果能減去b[1]若干次得到max(a[1],a[2])就是Yes,否則No
若b[1]>min(a[1],a[2]),說明最小值還沒達到,那就可以加速這個b[2]不斷減b[1]的過程,得到(b[1],b[2]%b[1])後再考慮
實際實現的時候,考慮b[2]可能是b[1]的倍數,但是b[2]不該變成0(因爲序列裏沒有0)
因此會給b[2]留一點,b[2]-=((b[2]-1)/b[1]*b[1]),這樣b[2]就最少是1了
設t=b[2]減掉的b[1]的倍數,如果某一步t<=0,說明本次操作不可減/什麼都沒減,顯然不合法
代碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sci(a) scanf("%d",&(a))
int n;
ll a[N+5],b[N+5],cntp;
string res;
void out(bool x){
if(!x)puts("IMPOSSIBLE");
else{
if(cntp>N){
puts("BIG");
printf("%lld\n",cntp);
}
else{
puts("SMALL");
reverse(res.begin(),res.end());
printf("%d\n%s\n",(int)res.size(),res.c_str());
}
}
}
bool ok(){
bool sm=1;
rep(i,1,n){
sm&=(a[i]==b[i]);
}
if(sm)return 1;
sm=1;
rep(i,1,n){
sm&=(a[i]==b[n+1-i]);
}
if(sm){
if(cntp<=N){
res+='R';
}
return 1;
}
return 0;
}
bool solve2(){
ll x=min(a[1],a[2]),y=max(a[1],a[2]);
while(1){
if(ok())return 1;
if(b[1]<b[2]){
ll t=0;
if(b[1]<x){
return 0;
}
else if(b[1]==x){//如果最小值已經對齊
t=(b[2]-y)/b[1];//b[2]->y(令b2至少爲y,嘗試令最大值對齊)
}
else{
t=(b[2]-1)/b[1];//b[2]->(b[2]%b[1])(且令b2至少爲1)
}
if(t<=0){//已經不能進行這樣的操作了
return 0;
}
else{
b[2]-=t*b[1];
if((cntp+=t)<=N){
res+=string(t,'P');
}
}
}
else if(b[1]>b[2]){
swap(b[1],b[2]);
if(cntp<=N){
res+='R';
}
}
else{
return 0;
}
}
}
bool solve3(){
while(1){
if(ok())return 1;
bool u=1,d=1;//up down
rep(i,1,n-1){
u&=(b[i]<b[i+1]);
d&=(b[i]>b[i+1]);
}
if(u){
per(i,n,2){
b[i]-=b[i-1];
}
if((++cntp)<=N){
res+='P';
}
}
else if(d){
reverse(b+1,b+n+1);
if(cntp<=N){
res+='R';
}
}
else{
return 0;
}
}
}
int main(){
sci(n);
rep(i,1,n)scanf("%lld",&a[i]);
rep(i,1,n)scanf("%lld",&b[i]);
if(n==1)out(a[1]==b[1]);
else if(n==2)out(solve2());
else out(solve3());
return 0;
}