「CTSC2017」吉夫特【Lucas 定理】【状压DP】

传送门

solution

\(Lucas\)定理:

\[\binom xy\equiv\binom{x\%2}{y\%2}\binom{x/2}{y/2}\pmod 2 \]

也就相当于设\(x_i,y_i\)分别是\(x,y\)二进制下的第\(i\)

那么:

\[\binom xy\equiv\prod_{i}\binom{x_i}{y_i}\pmod 2 \]

因为\(x_i,y_i\in{{0,1}}\),所以只有\(\binom{x_i}{y_i}\)的取值中只有\(\binom 01\)是等于\(0\)的,故

\[\binom {a_{b_{i-1}}}{a_{b_i}}\not =0 \]

意味着二进制下\(a_{b_i}\)的每一位都\(\le a_{b_{i-1}}\),将\(a_i\)看作是二进制下每一个\(1\)组成的集合,那么\(a_{b_i}\)必须是\(a_{b_{i-1}}\)的子集,因此我们直接设\(dp_i\)表示以\(i\)结尾的长度超过\(1\)的符合条件的子序列的个数,然后枚举\(i\)的子集转移即可:

code

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int N=(1<<20)+10;
int n,a[N],f[N],ans;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		for(int s=(a[i]-1)&a[i];s;s=(s-1)&a[i])
			f[s]=(f[s]+f[a[i]]+1)%mod;
		ans=(ans+f[a[i]])%mod;
	}
	cout<<ans;
	return 0;
}
原文地址:https://www.cnblogs.com/tqxboomzero/p/14218494.html