P3599 Koishi Loves Construction

题目描述
Koishi 决定走出幻想乡成为数学大师!
Flandre听说她数学学的很好,就给Koishi出了这样一道构造题:
Task1:试判断能否构造并构造一个长度为 n n n 1 … n 1 \ldots n 1n 的排列,满足其 n n n 个前缀和在模 n n n 的意义下互不相同
Taks2:试判断能否构造并构造一个长度为 n n n 1 … n 1 \ldots n 1n 的排列,满足其 n n n 个前缀积在模 n n n 的意义下互不相同
按照套路,Koishi假装自己根本不会捉,就来找你帮忙辣。

输入格式
第一行两个整数 X X X T T T,分别表示 T a s k Task Task 类型和测试点内的数据组数。
接下来 T T T 行,每行一个整数表示每组数据中的 n n n

输出格式
为了方便SPJ的编写,您需要遵从以下格式输出。
对于每组数据仅包含一行输出:
如果您认为当前数据不存在符合题意的构造,只需输出一个整数 0 0 0
如果您认为当前数据存在符合题意的构造却不会构造,只需输出一个整数 1 1 1
如果您认为当前数据存在符合题意的构造并成功构造,则需要先输出一个整数 2 2 2,再输出 n n n 个整数表示构造的方案。
每两个整数之间需要有空格作为分隔符

输入输出样例

输入 #1
1 1
8
输出 #1
2 8 7 6 5 4 3 2 1

输入 #2
2 1
11
输出 #2
2 1 2 3 5 10 6 7 4 9 8 11

思路
先来考虑 task1 ,我们根据题意简单分析可以知道, n n n 肯定放第一位,不然 它 和 前一位的 前缀和在模 n n n 的意义下肯定相同,然后接下来如果没有思路的话可以先暴力一波。
1 : 1 1:1 11
2 : 2    1 2:2~~1 22  1
3 : 3: 3
4 : 4    1    2    3 、 4    3    2    1 4:4~~1~~2~~3、4~~3~~2~~1 44  1  2  34  3  2  1
5 : 5: 5
6 : 6    1    4    3    2    5 、 6    2    5    3    1    4 、 … 6:6~~1~~4~~3~~2~~5、6~~2~~5~~3~~1~~4、\ldots 66  1  4  3  2  56  2  5  3  1  4
7 : 7: 7
8 : 8    1    6    3    4    5    2    7 、 … 8:8~~1~~6~~3~~4~~5~~2~~7、\ldots 88  1  6  3  4  5  2  7
可以明显看出,除了 1 1 1 的奇数好像都没有答案,这里再细致分析一下发现,对于除了 1 1 1 以外的奇数
∑ i = 1 n − 1 = n ∗ ( n − 1 ) 2 = n − 1 2 ∗ n \sum_{i=1}^{n-1}=\frac{n*(n-1)}{2}=\frac{n-1}{2}*n i=1n1=2n(n1)=2n1n
1... n 1...n 1...n 的和是 n n n 的倍数,这样子不管如何排列最后肯定会至少出现两个位置的前缀和模 n n n 意义下为 0 0 0,所以除 1 1 1 以外的奇数 task1 无解,那么对于偶数, n n n 越大,答案越多,但是我们仔细观察一下暴力出来的结果
2 : 2    1 2:2~~1 22  1
4 : 4    1    2    3 4:4~~1~~2~~3 44  1  2  3
6 : 6    1    4    3    2    5 6:6~~1~~4~~3~~2~~5 66  1  4  3  2  5
8 : 8    1    6    3    4    5    2    7 8:8~~1~~6~~3~~4~~5~~2~~7 88  1  6  3  4  5  2  7
可以总结如下:
n , 1 , n − 2 , 3 , n − 4 , 5 , . . . , n − 1 n,1,n-2,3,n-4,5,...,n-1 n1n23n45...n1
换一种写法
i ∈ o d d , a i = n + 1 − i ; i \in odd,a_i=n+1-i; ioddai=n+1i;
i ∈ e v e n , a i = i − 1 ; i \in even,a_i=i-1; ievenai=i1;
这样子 task1 就解决了。

再来考虑 task2,简答分析一下发现, 1 1 1 肯定得放在最前面,不然 它 和前一位 的前缀积在模 n n n 的意义下肯定相同,然后 n n n 肯定得放在最后面,因为 它 和之后所有位置的前缀积在模 n n n 的意义下都为 0 0 0,然后就好像没有思路了,再暴力一波:
1 : 1 1:1 11
2 : 1    2 2:1~~2 21  2
3 : 1    2    3 3:1~~2~~3 31  2  3
4 : 1    3    2    4 4:1~~3~~2~~4 41  3  2  4
5 : 1    2    4    3    5 、 1    3    4    2    5 5:1~~2~~4~~3~~5、1~~3~~4~~2~~5 51  2  4  3  51  3  4  2  5
6 : 6: 6
7 : 1    2    5    6    3    4    7 、 1    3    4    6    2    5    7 、 1    4    3    6    5    2    7 、 1    5    2    6    4    3    7 7:1~~2~~5~~6~~3~~4~~7、1~~3~~4~~6~~2~~5~~7、1~~4~~3~~6~~5~~2~~7、1~~5~~2~~6~~4~~3~~7 71  2  5  6  3  4  71  3  4  6  2  5  71  4  3  6  5  2  71  5  2  6  4  3  7
8 : 8: 8
除了 4 4 4 以外的合数好像无解,我们据此推一下 n n n 为合数的情形,发现一定存在 n = a ∗ b , a > 1 , b > 1 n=a*b,a>1,b>1 n=aba>1,b>1 ,还有 n = n n=n n=n 本身,这样的话,无论何种排列,至少会出现两个位置前缀积模 n n n 意义下为 0 0 0 的情况,而 n = 4 n=4 n=4 有解也可以顺便看出来是因为 4 = 2 ∗ 2 , a = b 4=2*2,a=b 4=22a=b 的缘故,所以可以知道除 4 4 4 外仅质数有解。那么如何构造这个解的序列呢?上面的暴力好像看不出什么名堂来,我们把它们做一下前缀积模 n n n
2 : 1    2 2:1~~2 21  2
3 : 1    2    3 3:1~~2~~3 31  2  3
5 : 1    2    3    4    5 、 1    3    2    4    5 5:1~~2~~3~~4~~5、1~~3~~2~~4~~5 51  2  3  4  51  3  2  4  5
7 : 1    2    3    4    5    6    7 、 1    3    5    2    4    6    7 、 1    4    5    2    3    6    7 、 1    5    3    4    2    6    7 7:1~~2~~3~~4~~5~~6~~7、1~~3~~5~~2~~4~~6~~7、1~~4~~5~~2~~3~~6~~7、1~~5~~3~~4~~2~~6~~7 71  2  3  4  5  6  71  3  5  2  4  6  71  4  5  2  3  6  71  5  3  4  2  6  7
发现前缀积模 n n n 下都存在 1 , 2 , . . . , n − 1 , 0 1,2,...,n-1,0 1,2,...,n1,0 的形式,即
m u l i ≡ i   ( m o d    n ) mul_i \equiv i~(mod~~n) mulii (mod  n)
设答案序列为 a n s ans ans,则 m u l i ≡ ( i − 1 ) × a n s i ≡ i   ( m o d    n ) mul_i \equiv (i-1) \times ans_i \equiv i~(mod~~n) muli(i1)×ansii (mod  n)
那么对于每个 m u l i mul_i muli ,求一下逆元就可以了。

#include<bits/stdc++.h>
using namespace std;
const int N = 1E5+10;
typedef long long ll;

int X,T,n;
int p[N],np[N],cnt;

void Prime()
{
	np[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!np[i]) p[++cnt]=i;
		for(int j=1;j<=cnt&&i*p[j]<N;j++)
		    np[i*p[j]]=1; 
	}
}

ll q_pow(ll x,ll m)
{
	ll res=1;
	while(m)
	{
		if(m&1) res=res*x%n;
		m>>=1;
		x=x*x%n; 
	}
	return res;
}

int main()
{
	scanf("%d%d",&X,&T);
	if(X==2) Prime();
	while(T--)
	{
		scanf("%d",&n);
		if(X==1)
		{
			if(n>1 && n&1) puts("0");
			else
			{
				putchar('2');
				for(int i=1;i<=n;i++)
			    {
			    	if(i&1) printf(" %d",n+1-i);
				    else printf(" %d",i-1);
				}
				puts("");
			}
		}
		else
		{
			if(np[n]&&n!=1&&n!=4) puts("0");
			else{
				if(n==1) puts("2 1");
				else if(n==4) puts("2 1 3 2 4");
				else{
					putchar('2');
					ll sum=1,tmp=1;	
					for(int i=1;i<=n-1;i++)
					{
						printf(" %d",tmp);
						tmp=q_pow(sum,n-2)*(i+1)%n;
						sum=sum*tmp%n;
					}
					printf(" %d\n",n);
				}
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值