不能全部改动的限制比较麻烦,我们可以先不加这个限制算,再去掉全部改动的方案数。后者可以把所有
ai
减
1
之后计算。
在计算的时候,我们枚举最高的被改动的一位【当然这首先要求往上的那些位异或和为零】。修改操作实际上就是把若干个这一位为
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=110,p=1000000007;
int a[maxn],dp[maxn][2],n;
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;
return x<0?x+p:x;
}
int solve()
{
int ret=0,t,x;
for (int k=29;k>=0;k--)
{
dp[0][0]=1;
for (int i=1;i<=n;i++)
if (a[i]&(1<<k))
{
dp[i][0]=inc((LL)dp[i-1][0]*(1<<k)%p,(LL)dp[i-1][1]*((a[i]&((1<<k)-1))+1)%p);
dp[i][1]=inc((LL)dp[i-1][1]*(1<<k)%p,(LL)dp[i-1][0]*((a[i]&((1<<k)-1))+1)%p);
}
else
{
dp[i][0]=(LL)dp[i-1][0]*((a[i]&((1<<k)-1))+1)%p;
dp[i][1]=(LL)dp[i-1][1]*((a[i]&((1<<k)-1))+1)%p;
}
t=0;
x=1;
for (int i=n;i>=1;i--)
{
if (a[i]&(1<<k))
{
ret=inc(ret,(LL)x*dp[i-1][t]%p);
t^=1;
}
x=(LL)x*((a[i]&((1<<k)-1))+1)%p;
}
if (t) break;
}
return ret;
}
int main()
{
//freopen("f.in","r",stdin);
int ans;
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
ans=solve();
for (int i=1;i<=n;i++) a[i]--;
ans=dec(ans,solve());
printf("%d\n",ans);
}