GYM103443E Composition with Large Red Plane, Yellow, Black, Gray, and Blue

官方题解好像是列出很多的线性方程,然后解出这个线性方程组。

这里提供另一个做法。

我们考虑每一个方框的长宽都必然可以写成两个等差数列的 \(ax+b\) 形式,表示扩大 \(x\) 倍后的长度,其中 \(b\) 就是最小的合法长度,我们发现对于合并操作,其中相同的一个维度实际上就是让这若干个等差数列求交,我们直接使用 \(\text{exCRT}\) 求解即可,而另一维度则根据前一维度进行调整即可。

#include<bits/stdc++.h>
using namespace std;

const int N=4e3+5,W=2e3+5,H=2e3+5;

int n=0,w,h;

vector<int> 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<tr[1].w.b||h<tr[1].h.b) printf("Impossible\n"),exit(0);
	if(tr[1].w.a&&tr[1].h.a){
		if((w-tr[1].w.b)%tr[1].w.a) printf("Impossible\n"),exit(0);
		if((h-tr[1].h.b)%tr[1].h.a) printf("Impossible\n"),exit(0);
		if((w-tr[1].w.b)/tr[1].w.a!=(h-tr[1].h.b)/tr[1].h.a) printf("Impossible\n"),exit(0);
	}
	else if(tr[1].w.a){
		if((w-tr[1].w.b)%tr[1].w.a) printf("Impossible\n"),exit(0);
		if(h!=tr[1].h.b) printf("Impossible\n"),exit(0);
		if((w-tr[1].w.b)/tr[1].w.a!=0) printf("Impossible\n"),exit(0);
	}
	else if(tr[1].h.a){
		if(w!=tr[1].w.b) printf("Impossible\n"),exit(0);
		if((h-tr[1].h.b)%tr[1].h.a) printf("Impossible\n"),exit(0);
		if((h-tr[1].h.b)/tr[1].h.a!=0) printf("Impossible\n"),exit(0);
	}
	else{
		if(w!=tr[1].w.b) printf("Impossible\n"),exit(0);
		if(h!=tr[1].h.b) printf("Impossible\n"),exit(0);
	}
	
	tr[1].w.b=w,tr[1].h.b=h,DFS(1,1,w,1,h);
	
	for(int i=1;i<=h;++i){
		for(int j=1;j<=w;++j) printf("%c",mp[i][j]?'*':' ');
		putchar('\n');
	}

	return 0;
}
posted @ 2022-03-09 15:13  Point_King  阅读(68)  评论(0编辑  收藏  举报