題目描述
題解
考慮最高位 ,如果 第 位爲 ,且 第 位爲 的話,那其他的 可以取任意值,因爲 可以取到 的任意一個數,所以可以調整一下,據此我們可以列出dp: 表示前 個數,有 個數第 位爲 ,可以得到方程的解的組數,那如果 爲 的話可以列出轉移式子 ,最後要記得除以 因爲其他數確定了,這個數也就確定了,所以只有 的貢獻,然後繼續遞歸即可
效率:
代碼
#include <bits/stdc++.h>
using namespace std;
const int P=1e9+7;
int n,m,a[55],f[55][55],w[55];
int solve(int x){
if (x<0) return 1;
f[0][0]=1;int u=0,v=0;
for (int i=1;i<=n;i++)
if (a[i]&(1<<x)){
u++;f[u][0]=1ll*f[u-1][0]*(1<<x)%P;
for (int j=1;j<=u;j++)
(f[u][j]+=(1ll*f[u-1][j]*(1<<x)%P+1ll*f[u-1][j-1]*((a[i]&((1<<x)-1))+1)%P)%P)%=P;
}
else for (int j=0;j<=u;j++) f[u][j]=1ll*f[u][j]*((a[i]&((1<<x)-1))+1)%P;
for (int i=0;i<u;i++)
if ((i&1)==((m>>x)&1))
(v+=1ll*f[u][i]*w[x]%P)%=P;
for (int i=0;i<=u;i++)
for (int j=0;j<=u;j++) f[i][j]=0;
if ((u&1)==((m>>x)&1))
return (v+solve(x-1))%P;
return v;
}
int main(){
w[0]=1;w[1]=(P+1)>>1;
for (int i=2;i<55;i++)
w[i]=1ll*w[i-1]*w[1]%P;
while(~scanf("%d%d",&n,&m)){
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("%d\n",solve(30));
}
return 0;
}