二进制序列额运算
二进制序列额运算
题意:
面对一个长度为 n 的数列 a。
∑(i,j,k,l=1~n) (a_i or a_j) xor (a_k and a_l)
结果对2^32取模
思路:
遇到相邻的数又加又减,大脑灵光一现,认为这题有规律可以找,
于是乎,杨辉三角数就有了着落,
一开始,使用暴力O(n^2)计算杨辉三角数,TLE了
后来看了jzjr的题解,知道了二项式定理,其中我们使用组合数计算杨辉三角数即可。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
const ll mod=1e9+7;
int n;
ll a[N],mul[N];
ll jc[N],jc_inv[N];
ll qpower(ll a,ll b,ll mod) {
ll res=1,mul=a;
while(b) {
if(b&1) res=res*mul%mod;
mul=mul*mul%mod; b>>=1;
}
return res;
}
void init() {
jc[0]=jc_inv[0]=1;
for(int i=1;i<=100000;i++) {
jc[i]=jc[i-1]*i%mod;
}
jc_inv[100000]=qpower(jc[100000],mod-2,mod);
for(int i=99999;i>=1;i--) {
jc_inv[i]=jc_inv[i+1]*(i+1)%mod;//????
}
}
ll C(ll i,ll j) {
if(j>i) return 0;
if(j==0) return 1;
return jc[i]*jc_inv[i-j]%mod*jc_inv[j]%mod;
}
int main() {
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
init();
ll res1=0,res2=0,chu;
int lim=(n+1)/2;
for(int i=1;i<=lim;i++) {
mul[i]=C(lim-1,i-1);
}
for(int i=1;i<=lim;i++) {
if(i&1) {
res1+=mul[i]*a[i*2-1];
if(res1<0) {
chu=res1/mod;
res1=(chu+1)*mod+res1;
}
res1%=mod;
}
else {
res1+=(-mul[i]*a[i*2-1]);
if(res1<0) {
chu=res1/mod;
res1=(chu+1)*mod+res1;
}
res1%=mod;
}
}
if(n%2==0) {
for(int i=1;i<=lim;i++) {
if(i&1) {
res2+=(mul[i]*a[i*2]);
if(res2<0) {
chu=res2/mod;
res2=(chu+1)*mod+res2;
}
res2%=mod;
}
else {
res2+=(-mul[i]*a[i*2]);
if(res2<0) {
chu=res2/mod;
res2=(chu+1)*mod+res2;
}
res2%=mod;
}
}
}
res1+=res2;
if(res1<0) {
chu=res1/mod;
res1=(chu+1)*mod+res1;
}
res1%=mod;
cout<<res1;
return 0;
}