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;
}