CF1513B 题解
CF1513B 题解
题面
题意
给定一个数组 \(a\),问在 \(a\) 中有多少种排列满足对于任意 \(i(i\in[1,n))\) 有 \(a_1\&a_2\&a_3\&\cdots\&a_i=a_{i+1}\&a_{i+2}\&a_{i+3}\&\cdots\&a_n\)。
前置知识
- 位运算,知道与运算是两者都为真则为真,两者有一者为假则为假,并能推出 \(a\&a=a(a\in\mathbb{N})\)。
思路
不妨设 \(cnt=a_1\&a_2\&a_3\&\cdots\&a_n\)。
依题,\(a_1=a_2\&a_3\&a_4\&\cdots\&a_n\);
两边同时与上 \(a_1\),则有 \(a_1=cnt\)。
依题,\(a_1\&a_2\&a_3\&\cdots\&a_{n-1}=a_n\);
两边同时与上 \(a_n\),则有 \(a_n=cnt\)。
依题,\(a_1\&a_2=a_3\&a_4\&a_5\&\cdots\&a_n\),
两边同时与上 \(a_1\&a_2\),则有 \(a_1\&a_2=cnt\)。
已知 \(a_1=cnt\),所以 \(a_2\) 可以为任意数。
同理,\(a_3,a_4\cdots,a_{n-1}\) 也可以为任意数。
于是,问题就转化为,给定一个数组 \(a\),求有多少种排列满足首位均为 \(cnt\)。
于是再设 \(num\) 为 \(a\) 数组中等于 \(cnt\) 的个数。
于是首位两个是定的,有小学学过的组合知识,首位的方案数为 \(num\times(num-1)\),而中间排列的方式为 \((n-2)!\)。
故,答案为 \(num\times(num-1)\times(n-2)!\)。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define mod 1000000007
using namespace std;
long long n,a[200005],T,num,cnt,ans;
//cnt为a1^a2^a3^...^an
//num为a数组中与cnt相同的个数
int main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
cnt=0;num=0;//初始化
for(int i=1; i<=n; i++){
scanf("%lld",&a[i]);
if(i>1) cnt&=a[i];
else cnt=a[i];
}
for(int i=1; i<=n; i++) if(a[i]==cnt) num++;
ans=(num-1)*num%mod;
for(int i=1; i<=n-2; i++) ans=ans*i%mod;;//计算(n-2)!
printf("%lld\n",ans);
}
return 0;
}

浙公网安备 33010602011771号