题目大意:给定一个数据,求其全排列中满足 以下条件的数量。
大致思路:如果想要等式左边等于右边,即二进制的每一位相等,那么必须找到一个数,即&上其他数对整个数不会产生影响,将这两个数放到等式两边,即可一定满足等式两边相等,那么怎么求这个数呢?
cin>>a[0];
ll k=a[0]; //将k&上数组中所有的数,找到那个不会影响等式两边的数
for(int i=1;i<n;i++)
{
scanf("%lld",&a[i]);
k=(k&a[i]);
}
ll cnt=0;
for(int i=0;i<n;i++) //求出不会影响等式两边数的个数cnt
if( a[i]-k ==0)
cnt++;
将这个数放到等式两边,可保证等式两边一定相等。
答案即为 左边选一个数,右边选一个数,然后将剩下的数全排列即可。
全部代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2*1e5+10,M=1e9+7;
typedef long long ll;
int n;
ll a[N];
int main()
{
int t;cin>>t;
while (t--)
{
cin>>n;
cin>>a[0];
ll k=a[0];
for(int i=1;i<n;i++)
{
scanf("%lld",&a[i]);
k=(k&a[i]);
}
ll cnt=0;
for(int i=0;i<n;i++)
if( a[i]-k ==0)
cnt++;
if(cnt<2) puts("0");
else
{
ll ans=1;
ans=cnt*(cnt-1)%M;
for(int i=1;i<=n-2;i++) ans=(ans*i)%M;
cout<<ans<<endl;
}
}
return 0;
}