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\)

前置知识

  1. 位运算,知道与运算是两者都为真则为真,两者有一者为假则为假,并能推出 \(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;
}
posted @ 2025-01-29 15:44  naroto2022  阅读(9)  评论(0)    收藏  举报