2020牛客暑期多校训练营(第六场)G Grid Coloring

2020牛客暑期多校训练营(第六场)G

在这里插入图片描述
在这里插入图片描述

题意:
给定一个边长为n的正方形,有k种不同颜色的火柴,询问一种合理的摆放位置,使得其满足以下限制:
(1) 所有颜色的火柴数目应该相同
(2) 图中不存在一个单色循环
(3) 某一行或一列至少存在两种颜色。

题解:
其实这题十分简单,赛中忘记特判n=1导致wa了。
先排除没有答案的情况,n=1,k=1,2 * n * (n + 1) % k != 0。
解开这题的关键,是想办法构造每一个小正方形对边颜色不等,容易证明符合上面三种限制。
考虑四种情况:
(1) n < k
颜色的种类大于每一行所需的火柴数量,第一行放置1-n,第二行从n+1开始放,按照这种顺序一直放到k后重新回到1开始,那么第一行的第一根火柴必定跟第二行的第一根火柴颜色不同,同理,容易得到一个符合题意的构造。

(2) n = k
思路是第一行放置1,2,…,n,第二行放置2,3,…,n,第三行放置1,2,…,n,依次类推,列的构造和行的构造一样。

(3) n < k && n % k == 0
举个例子,n = 12 和 k = 4
1 2 3 4 1 2 3 4 1 2 3 4
2 3 4 1 2 3 4 1 2 3 4 1
1 2 3 4 1 2 3 4 1 2 3 4
2 3 4 1 2 3 4 1 2 3 4 1
按照这种构造方式重复构造,思路和第二种相似。

(4) n < k && n % k != 0
举个例子,n = 9 和 k = 5
1 2 3 4 5 1 2 3 4
5 1 2 3 4 5 1 2 3
4 5 1 2 3 4 5 1 2
3 4 5 1 2 3 4 5 1
2 3 4 5 1 2 3 4 5
按照这种构造方式重复构造,思路和第一种相似。

AC_CODE:

	int n,k;
	R(n,k);
	if (2 * n * (n + 1) % k != 0 || k == 1 || n == 1) {
		printf("-1\n");
		return;
	}
	if(k > n) {
		int ans = 1;
		FOR(i,1,2*(n+1)) {
			FOR(j,1,n-1) {
				printf("%d ",ans++);
				if(ans > k) ans -= k;
			}
			printf("%d\n",ans++);
			if(ans > k) ans -= k;
		}
	} else if(k == n) {
		int ans = 1;
		bool ok = 0;
		FOR(i,1,2*(n+1)) {
			if(!ok) {
				FOR(j,1,n) {
					printf("%d%c",ans++,(j==n?'\n':' '));
				}
			} else {
				FOR(j,1,n-1) {
					printf("%d ",++ans);
				}
				printf("1\n");
			}
			ok ^= 1;
			ans = 1;
		}
	} else if(n % k == 0) {
		int t = n / k;
		int ans = 1;
		bool ok = 0;
		FOR(i,1,2*(n+1)) {
			if(!ok) {
				FOR(j,1,n-1) {
					if(ans > k) ans -= k;
					printf("%d ",ans++);
				}
				if(ans > k) ans -= k;
				printf("%d\n",ans++);
			} else {
				FOR(j,1,n-1) {
					if(ans == k) ans -= k;
					printf("%d ",++ans);
				}
				if(ans == k) ans -= k;
				printf("%d\n",++ans);
			}
			ok ^= 1;
			ans = 1;
		}
	} else {
		int ans = 1;
		FOR(i,1,2*(n+1)) {
			FOR(j,1,n-1) {
				if(ans > k) ans -= k;
				printf("%d ",ans++);
			}
			if(ans > k) ans -= k;
			printf("%d\n",ans++);
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值