2022ICPC沈阳站 Problem F. Half Mixed

构造题。
题意:给定n,m,求一个nm的0/1矩阵,满足纯子矩阵数==杂子矩阵数。(纯子矩阵为内部只含有0或1的子矩阵,杂子矩阵反之)
其中 n,m<=1e6,n
m<=5e6.
显然杂子矩阵不好处理,那我们计算纯子矩阵。我们可以将矩阵划分为一列0一列1的形式,保证纯子矩阵能够简单的得到,我们的总的子矩阵个数为(n+1) * n/2 * (m+1) * m/2(被2整除,否则无解),而当交错赋值时,纯子矩阵个数为(n+1) * n/2 * m,当然若m为奇数,swap(n , m)。我们观察再发现,相同的两列会产生多(n+1) * n/2,相同地k列会多产生 (k-1) * k/2 *(n+1) * n/2个纯子矩阵,故我们可以使得前k1个列均为0,接下来k2列为1,,,直至产生地多的纯子矩阵个数==(m+1) * m/4 - m,每次贪心地减少尽可能多的,易知必定有解。
代码:

#define int long long
using namespace std;
template <typename T> void read(T &t) {
	t=0; char ch=getchar(); int f=1;
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	do { (t*=10)+=ch-'0'; ch=getchar(); } while ('0'<=ch&&ch<='9'); t*=f;
}
template <typename T> void write(T t) {
	if (t<0) { putchar('-'); write(-t); return; }
	if (t>9) write(t/10);
	putchar('0'+t%10);
}
int cnt[1000100],tot,a[2000100];
int g[7001000];
void solve(){
	int ok=0;
	tot=0;
	int n,m;read(n),read(m);
	int w=n*(n+1)/2*m*(m+1)/2;
	if(w%2){
		puts("No");
		return;
	}
	if(m*(m+1)/2%2) swap(n,m),ok=1;
	int now=m*(m-3)/4;	
	while(now){
		int p=lower_bound(a+2,a+1000010,now)-a;
		while(a[p]>now) p--;
		now-=a[p];
		cnt[++tot]=p;
	}
	int q=0,pre=1;
	for(int i=1;i<=tot;i++){
		q^=1;
		for(int j=pre;j<=pre+cnt[i]-1;j++){
			for(int k=1;k<=n;k++){
				g[k+j*(n+1)]=q;
			}
		}
		pre=pre+cnt[i];
	}
	for(int i=pre;i<=m;i++){
		q^=1;
		for(int j=1;j<=n;j++){
			g[j+(n+1)*i]=q;
	}
	}
	puts("Yes");
	if(!ok){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
			write(g[i+j*(n+1)]);printf(" ");
			}
			cout<<endl;
		}
	}
	else{
		for(int i=1;i<=m;i++){
			for(int j=1;j<=n;j++){
				write(g[j+i*(n+1)]);
				printf(" ");
			}
			puts("");
		}
	}
}
signed main(){
	int T;read(T);
	for(int i=2;i<=1000010;i++){
		a[i]=(i-1)*i/2;
	}
	while(T--) solve();
}
posted @   wrong,anser  阅读(455)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示