[2018.11.05 T1] 喝牛奶

TomTomTom是一只聪明的猫,他需要找到一种或两种喝牛奶的顺序,以便收集到所有种类的卡片。这涉及到构造特定的数列,确保模n意义下的前缀和包含0到n-1的所有值。当n为偶数时,存在解决方案,通过将数字配对,使其和为n+1或n-1,形成两个有效的排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

暂无链接

喝牛奶

题目描述

这一天 T o m Tom Tom 正在喝牛奶。

T o m Tom Tom的主人买来了 n n n 桶牛奶,第 i i i桶牛奶的重量是 i i i吨。由于主人心情不好,她随机地把这些牛奶的顺序打乱了,然后把它们丢给了 T o m Tom Tom

T o m Tom Tom 会从第一桶牛奶开始喝,每次喝完一整桶牛奶,由于猫的消化能力及其强大,所以每当 T o m Tom Tom的肚子里有 n n n吨牛奶时,他会开启究极消化模式,把肚子中的牛奶清零。与此同时,在喝完每一桶牛奶后,他会记录下自己肚子里剩余牛奶的重量 w w w,并从主人那里领取一张写着数字 w w w的卡片,显然 w ∈ [ 0 , n − 1 ] w∈[0,n−1] w[0,n1]

由于 T o m Tom Tom是一只十分好学的好猫,在日复一日的喝牛奶活动中,他渐渐开始好奇,是否存在某一些给定牛奶的顺序,使得 T o m Tom Tom可以集齐全部的 n n n 种卡片?

本来 T o m Tom Tom 想问你有多少种这样的方案,但是由于他牛奶喝多了,自己也无法解决这个问题,所以,他现在准备请你给出一种或两种可以使得他集齐所有卡片的给定牛奶的顺序。

一句话题意: 请构造两个 1 ∼ n 1∼n 1n的排列,使得在模 n n n意义下对这个排列进行前缀和操作后, 0   n − 1 0 ~ n−1 0 n1中的每个数在新的序列中都出现了一次。如果没有这样的排列,请输出 − 1 −1 1

输入格式

一个正整数 n n n

输出格式

第一行一个数字: − 1 −1 1 1 1 1 2 2 2

如果你输出了 − 1 −1 1,则代表你认为不存在这样的排列。

如果你输出了 1 1 1,则代表你即将输出一个这样的排列。

如果你输出了 2 2 2,则代表你即将输出两个这样的排列。

如果你在第一行输出了 1 1 1 2 2 2,那么你需要输出 ( 一行,一个 1   n 1~n 1 n的排列 ) 或 (两行,两个不相同的 1   n 1~n 1 n的排列) 。

数据保证如果存在这样的排列,则至少有两个合法的排列。

输入样例

6

输出样例

2
6 2 5 3 1 4
6 5 2 3 4 1

数据范围

对于 10 % 10\% 10%的数据,保证 2 &lt; n ≤ 8 2&lt;n≤8 2<n8

对于 30 % 30\% 30%的数据,保证 2 < n ≤ 12 2<n≤12 2n12

对于 100 % 100\% 100%的数据,保证 2 &lt; n ≤ 200000 2&lt;n≤200000 2<n200000

评分标准

本题使用 s p e c i a l   j u d g e special\ judge special judge 进行评测。
如果你的输出不符合输出格式或者答案错误,那么你将获得本测试点 0 % 0\% 0% 的分数。
如果你输出了一个正确排列和一个错误排列,那么你将获得本测试点 0 % 0\% 0% 的分数。
如果你只输出了一个正确排列,那么你将获得本测试点 40 % 40\% 40% 的分数。
如果你的程序正确地输出了结果,那么你将获得本测试点 100 % 100\% 100% 的分数。
如果你的程序导致 s p e c i a l   j u d g e special\ judge special judge 出现异常,那么你将会获得该测试点 0 % 0\% 0% 的分数(包括但不仅限于输出的东西不是一个排列、第一行输出了奇怪的东西、输出的排列中加入了奇怪的字符等)

题解

可能需要打表找一找规律?

由于题目保证如果有答案的话至少有两个合法排列,所以我们不用考虑 n = 1 或 2 n=1或2 n=12的情况,直接看 n ≥ 3 n\ge 3 n3的。

首先,如果 n n n放在排列中间,那么肯定会有两个一样的前缀和,所以 n n n一定要放在开头。

n n n为奇数时,由于 n n n一定在第一个, ∑ i = 1 n i ≡ 0 m o d &ThinSpace;&ThinSpace; n \sum_{i=1}^ni\equiv0\mod n i=1ni0modn所以后面一定有两个重复的数,输出 − 1 -1 1

那么只剩 n n n为偶数的情况,为了让模意义下的前缀和不重不漏,不妨将数两两分为一组,使每一组和为 n + 1 n+1 n+1
n , ( n − 1 , 2 ) , ( n − 3 , 4 ) , ⋯ &ThinSpace; , 1 n,(n-1,2),(n-3,4),\cdots,1 n,(n1,2),(n3,4),,1

第二组的话,我们可以让每组的数字和为 n − 1 n-1 n1
n , ( 1 , n − 2 ) , ( 3 , n − 4 ) , ⋯ &ThinSpace; , n − 1 n,(1,n-2),(3,n-4),\cdots,n-1 n,(1,n2),(3,n4),,n1

代码
#include<cstdio>
int n;
void in(){scanf("%d",&n);}
void ac()
{
	if(n&1){puts("-1");return;}
	printf("2\n%d ",n);for(int i=1;i<n-1;i+=2)printf("%d %d ",n-i,i+1);puts("1");
	printf("%d ",n);for(int i=1;i<n-1;i+=2)printf("%d %d ",i,n-i-1);printf("%d",n-1);
}
main(){in(),ac();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值