二进制序列额运算

二进制序列额运算

题意:

面对一个长度为 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;
}
posted on 2024-11-03 21:05  Ueesugi_sakura  阅读(5)  评论(0编辑  收藏  举报