[AT165E]Rotation Matching

280 篇文章 1 订阅

题目

传送门 to AtCoder

思路

你看,其实每个人都会把 [ 1 , n ] [1,n] [1,n] 的所有编号拿一遍。所以,下面这句话就是顺理成章的:场地上的两个数字的差不能重复

譬如,假设一个场地上是 ( a , a + Δ ) (a,a+\Delta) (a,a+Δ) 而另一个是 ( b , b + Δ ) (b,b+\Delta) (b,b+Δ) ,那么某两个编号相差 Δ \Delta Δ 的人就会在这两个场地上都比赛。

类似的,二者的差可能不是正数。意即:一个人拿 a + Δ a+\Delta a+Δ 而另一个人拿 a a a ,二者的编号差也可能是 a − ( a + Δ ) = − Δ ≡ n − Δ ( m o d n ) a-(a+\Delta)=-\Delta\equiv n-\Delta\pmod{n} a(a+Δ)=ΔnΔ(modn) ,因为编号会自动取模 n n n 。当然,这种情况会在两个差值(大减小)的和为 n n n 时出现。

我们可以用集合来表示所有的差值。当 n n n 为奇数时,很好找到这样的差值 { 1 , 3 , 5 , … , n − 2 } \left\{1,3,5,\dots,n-2\right\} {1,3,5,,n2}

题面保证了 2 m + 1 ≤ n 2m+1\le n 2m+1n m ≤ n − 1 2 m\le\frac{n-1}{2} m2n1 ,故数量足够。任意两者的和为奇数+奇数=偶数,不可能等于 n n n 。能够构造出来吗?使用 俄罗斯套娃

可以使用 ( 1 , n − 1 ) , ( 2 , n − 2 ) , ( 3 , n − 3 ) , … , ( n − 1 2 , n + 1 2 ) (1,n-1),(2,n-2),(3,n-3),\dots,\left(\frac{n-1}{2},\frac{n+1}{2}\right) (1,n1),(2,n2),(3,n3),,(2n1,2n+1)

至于 n n n 为偶数的情况,就得动点小心思。我们可以写出这样的差值 { x | x 2 ∈ Z , x < n 2 } ⋃ { x | x − 1 2 ∈ Z , x > n 2 } \left\{x\middle|\frac{x}{2}\in\Z,x<\frac{n}{2}\right\}\bigcup\left\{x\middle|\frac{x-1}{2}\in\Z,x>\frac{n}{2}\right\} {x2xZ,x<2n}{x2x1Z,x>2n}

个数有多少个?可以分类讨论 n / 2 n/2 n/2 的奇偶性。在 n / 2 n/2 n/2 为奇数时,大小为 ( n 4 − 1 2 ) + ( n 4 − 1 2 ) = n 2 − 1 (\frac{n}{4}-\frac{1}{2})+(\frac{n}{4}-\frac{1}{2})=\frac{n}{2}-1 (4n21)+(4n21)=2n1 ,显然够用;在 n / 2 n/2 n/2 为偶数时,大小为 ( n 4 − 1 ) + ( n 4 ) = n 2 − 1 (\frac{n}{4}-1)+(\frac{n}{4})=\frac{n}{2}-1 (4n1)+(4n)=2n1 ,仍然够用。

相加会不会得到 n n n 呢?因为 n n n 是偶数,所以只能是奇数+奇数,或者偶数+偶数。但是奇数都小于 n 2 \frac{n}{2} 2n ,和必然小于 n n n ;偶数都大于 n 2 \frac{n}{2} 2n ,和必定大于 n n n ,故方案可行。

怎么构造呢?仍然使用俄罗斯套娃。小于 n 2 \frac{n}{2} 2n 的在最内层,更大的在外层继续套上去。

代码

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;

int main(){
	int n, m;
	scanf("%d %d",&n,&m);
	if(n%2 == 1){
		int l = 1, r = n-1;
		for(int i=1; i<=m; ++i)
			printf("%d %d\n",l++,r--);
	}
	else if(n%2 == 0){
		int l = n/2, r = n/2+1;
		for(int i=1; i<=m; ++i){
			printf("%d %d\n",l--,r++);
			if((r-l)%2 and r-l >= n/2)
				++ r;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值