GYM103443E Composition with Large Red Plane, Yellow, Black, Gray, and Blue
官方题解好像是列出很多的线性方程,然后解出这个线性方程组。
这里提供另一个做法。
我们考虑每一个方框的长宽都必然可以写成两个等差数列的 \(ax+b\) 形式,表示扩大 \(x\) 倍后的长度,其中 \(b\) 就是最小的合法长度,我们发现对于合并操作,其中相同的一个维度实际上就是让这若干个等差数列求交,我们直接使用 \(\text{exCRT}\) 求解即可,而另一维度则根据前一维度进行调整即可。
#include
using namespace std;
const int N=4e3+5,W=2e3+5,H=2e3+5;
int n=0,w,h;
vector e[N];
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int exgcd(int a,int b,int &x,int &y){
if(b==0) return x=1,y=0,a;
int _x,_y,tmp=exgcd(b,a%b,_x,_y);
return x=_y,y=_x-a/b*_y,tmp;
}
struct Line{int a,b;};
Line operator + (Line f,Line g){
int x,y,tmp=exgcd(f.a,-g.a,x,y);
if(!tmp){
if(g.b!=f.b) printf("Impossible\n"),exit(0);
return f;
}
x*=(g.b-f.b)/tmp,y*=(g.b-f.b)/tmp,tmp=abs(tmp);
if(x<0&&g.a){
int cnt=(0-x+g.a/tmp-1)/(g.a/tmp);
x+=g.a/tmp*cnt,y+=f.a/tmp*cnt;
}
if(y<0&&f.a){
int cnt=(0-y+f.a/tmp-1)/(f.a/tmp);
x+=g.a/tmp*cnt,y+=f.a/tmp*cnt;
}
if(f.a&&g.a){
int cnt=min(x/(g.a/tmp),y/(f.a/tmp));
x-=g.a/tmp*cnt,y-=f.a/tmp*cnt;
}
if(x<0||y<0) printf("Impossible\n"),exit(0);
Line res=(Line){f.a*g.a/tmp,f.a*x+f.b};
if(res.a>1000) res.a=0;
if(res.b>1000) printf("Impossible\n"),exit(0);
return res;
}
struct Node{int dep,s;Line w,h;}tr[N];
int read(int dep){
int u=++n;
scanf("%d",&tr[u].s),tr[u].dep=dep;
if(!tr[u].s){
int w,h,tmp;scanf("%d%d",&w,&h),tmp=gcd(w,h),w/=tmp,h/=tmp;
tr[u].w.a=w,tr[u].w.b=tr[u].w.a+2,tr[u].h.a=h,tr[u].h.b=tr[u].h.a+2;
}
else for(int i=1;i<=tr[u].s;++i) e[u].push_back(read(dep+1));
return u;
}
bool mp[W][H];
void dfs(int u){
for(auto v:e[u]) dfs(v);
if(!tr[u].s);
else if(tr[u].dep&1){
tr[u].w=(Line){1,0},tr[u].h=(Line){0,1-tr[u].s};
for(auto v:e[u]) tr[u].w=tr[u].w+tr[v].w;
for(auto v:e[u]){
if(tr[v].w.a){
int tmp=tr[u].w.a/tr[v].w.a,TMP=(tr[u].w.b-tr[v].w.b)/tr[v].w.a;
tr[u].h.a+=tr[v].h.a*tmp,tr[u].h.b+=tr[v].h.a*TMP+tr[v].h.b;
}
else{
int tmp=(tr[u].w.a==0),TMP=(tr[u].w.b-tr[v].w.b==0);
tr[u].h.a+=tr[v].h.a*tmp,tr[u].h.b+=tr[v].h.a*TMP+tr[v].h.b;
}
}
}
else{
tr[u].h=(Line){1,0},tr[u].w=(Line){0,1-tr[u].s};
for(auto v:e[u]) tr[u].h=tr[u].h+tr[v].h;
for(auto v:e[u]){
if(tr[v].h.a){
int tmp=tr[u].h.a/tr[v].h.a,TMP=(tr[u].h.b-tr[v].h.b)/tr[v].h.a;
tr[u].w.a+=tr[v].w.a*tmp,tr[u].w.b+=tr[v].w.a*TMP+tr[v].w.b;
}
else{
int tmp=(tr[u].h.a==0),TMP=(tr[u].h.b-tr[v].h.b==0);
tr[u].w.a+=tr[v].w.a*tmp,tr[u].w.b+=tr[v].w.a*TMP+tr[v].w.b;
}
}
}
}
void DFS(int u,int l,int r,int L,int R){
// printf("%d %d %d %d %d\n",u,l,r,L,R);
if(!tr[u].s){
for(int i=L;i<=R;++i) mp[i][l]=mp[i][r]=true;
for(int j=l;j<=r;++j) mp[L][j]=mp[R][j]=true;
return ;
}
else if(tr[u].dep&1){
int lst=L;
for(auto v:e[u]){
if(tr[v].w.a){
int tmp=tr[u].w.a/tr[v].w.a,TMP=(tr[u].w.b-tr[v].w.b)/tr[v].w.a;
tr[v].h.b=tr[v].h.a*TMP+tr[v].h.b,tr[v].h.a*=tmp;
DFS(v,l,r,lst,lst+tr[v].h.b-1),lst+=tr[v].h.b-1;
}
else{
int tmp=(tr[u].w.a==0),TMP=(tr[u].w.b-tr[v].w.b==0);
tr[v].h.b=tr[v].h.a*TMP+tr[v].h.b,tr[v].h.a*=tmp;
DFS(v,l,r,lst,lst+tr[v].h.b-1),lst+=tr[v].h.b-1;
}
}
}
else{
int lst=l;
for(auto v:e[u]){
if(tr[v].h.a){
int tmp=tr[u].h.a/tr[v].h.a,TMP=(tr[u].h.b-tr[v].h.b)/tr[v].h.a;
tr[v].w.b=tr[v].w.a*TMP+tr[v].w.b,tr[v].w.a*=tmp;
DFS(v,lst,lst+tr[v].w.b-1,L,R),lst+=tr[v].w.b-1;
}
else{
int tmp=(tr[u].h.a==0),TMP=(tr[u].h.b-tr[v].h.b==0);
tr[v].w.b=tr[v].w.a*TMP+tr[v].w.b,tr[v].w.a*=tmp;
DFS(v,lst,lst+tr[v].w.b-1,L,R),lst+=tr[v].w.b-1;
}
}
}
}
int main(){
// freopen("1.in","r",stdin);
cin>>w>>h,read(0),dfs(1);
if(w
相关