AT2271 [ARC066A] Lining Up 题解

题目大意

\(n\) 个人排成一列,每个人左边的人数减去右边的人数的绝对值已经固定,问有几种排列情况(如果报告错误,输出 \(0\))。

思路

找规律

举一个例子,当 \(n=5\) 的时候,从左到右他们的 \(A_{i}\) 就分别为 \(4\) \(2\) \(0\) \(2\) \(4\) ; 当 \(n=6\) 的时候,从左到右他们的 \(A_{i}\) 就分别为 \(5\) \(3\) \(1\) \(1\) \(3\) \(5\)。由此我们发现,\(A_{i}\)的大小是左右对称的,那么导致有多种排列的原因就是绝对值:一个数可以出现在左半边,也可以出现在右半边。于是我们得到结论:

\[A = 2^{\lfloor \frac{n}{2}\rfloor} \]

那么报告错误的话,就说明每个 \(A_{i}\) 出现的次数不是两次(\(0\) 出现一次),我们给一个桶,进行判断即可。

代码实现

#include<bits/stdc++.h>
const int N=1e5+5;
const int MOD=1e9+7;
using namespace std;

int n;
int a[N];
int tong[N];
int ans=1;

int main()
{
	/*freopen("queue.in","r",stdin);
	freopen("queue.out","w",stdout);*/
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),tong[a[i]]++;/*看看出现次数是否是两次*/
	bool flag=1;/*flag来验证是否正确*/
	if(n%2!=0)/*当n为奇数的时候才需要特判0,n为偶数的时候就不需要了*/
	{
		if(tong[0]==1)
		{
			for(int i=2;i<=n-1;i+=2)/*n为奇数的时候每个Ai为偶数,n为偶数的时候相反*/
				if(tong[i]!=2) /*不对就把flag设为0*/
				{
					flag=0;
					break;
				}
		}
		else flag=0;
	}
	else
	{
		for(int i=1;i<=n-1;i+=2)
			if(tong[i]!=2) 
				{
					flag=0;
					break;
				}
	}/*同理*/
	if(flag)/*验证是否正确*/
	{
		for(int i=1;i<=n/2;i++)
			ans=((ans%MOD)*2)%MOD;/*按照规律乘上2就可以了,这里数据较小,可以不用快速幂*/
		printf("%d",ans%MOD);
	}
	else printf("0");
	return 0;
} 
posted @ 2023-05-25 21:44  Bloodstalk  阅读(7)  评论(0编辑  收藏  举报