题目:
题目思路:
首先我们知道a数组中所有值的和为m
我们要求a数组中所有值异或的值最大的情况数
我们要先抓住题目的第一个条件
(使a数组中所有值的异或的值为最大)
【对于异或还不清楚的同学可以网上学习一下】
我们要想使异或的值最大
就要保证越高位的数上面位1可以使异或为最大
我们可以推出(大家可以自己举更多的例子去了解一下2二进制的规律)
要想使所有的异或结果最大
可以通过观察规律得出异或的最大值就为m自己
然后根据条件2(a数组中有n个数)进行如下步骤
具体操作:
1.先就取m的二进制上的所有数为a数组的一个数,数组里面其他数皆为0。
(该情况为能取异或后为最大值的一种情况)
2.在保证位数上0和1改变数字的情况可以对其进行改变所在的数组的数
3.在确定了步骤1和步骤2的情况下(即每个位上的数为0或1)
我们再观察变量n
通过二进制的规律我们可以得到:
每个位上1移动到数组中的另外一个数会使数组形成新的方案数
对于每个位上的1我们可以移动到数组a中n个数中的任意一个数
那么我们可以得出一个位上的1移动会造成n种情况
(注:对于0的移动不会影响每个数的大小所以不考虑)
4.确定了思路我们就可以将思路写成代码
代码详解:
#include<stdio.h>
#include<iostream>
using namespace std;
typedef long long ll;
#include<string>
const int N=(ll)1e9+7;
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
n%=N;//按题目要求对n取模
ll s=1;
while(m)//对m的二进制上每个位上的数考虑
{
if(m&1) s=s*n%N;//如果二进制的最后一位为1(m为奇数)那么就进行方案数统计
m=m>>1;//向右边移动一位(对m除以2)进行下一位的判断
}
cout<<s;//输出答案
return 0;
}
PS:大家对于二进制感兴趣的可以更多取了解一下0和1的奥秘,另外博客中所写的内容不怎么理解的可以自己多举几个例子来摸索其中的规律,这会帮你理解博客,谢谢阅读,不妨给个三连,嘿嘿(/doge)。