Description
Link.
求满足
的子序列个数。
Solution
哇哦。
式子后面的 (dbinom{a_{b_{i}-1}mod2}{a_{b_{i}mod2}}) 一共有四种情况,其中只有 (dbinom{0}{1}=0)。其他都为 (1)。
意味着只要出现 (a_{b_{i}-1}equiv0mod2) 且 (a_{b_{i}}equiv1mod1) 的情况,整个式子就为零了。
结论:(dbinom{n}{m}equiv0space(operatorname{mod}2)) 当且仅当 (noperatorname{bitand}m=m)。
证明(也许不是特别严谨):我们可以知道:
我们发现:
这一坨,就是在一直进行二进制移位,(operatorname{shr}1)。
那么我们可以得出一个结论:如果对于我们记 ((n)_{k}) 表示 (n) 在二进制意义下的第 (k) 位。((n)_{k}in[0,1])
那么对于 (forall i),有 ((n)_{i}=0) 且 ((m)_{i}=1),那么 (dbinom{n}{m}equiv0space(operatorname{mod} 2))。
所以 (noperatorname{bitand}m=m),证毕。
我们题目要求的是最后算出来是个奇数,那么就不能存在 (a_{b_{i}-1}operatorname{bitand}a_{b_{i}}=a_{b_{i}})。
也就是 (a_{b_{i}}) 为 (a_{b_{i}-1}) 的子集。
接下来我们可以设计一个 DP,我们设 (f_{i}) 为以 (a_{i}) 为开头的答案。
那么转移就是加法原理:
其中 (t_{i}) 表示 (i) 在序列中的位置。
时间复杂度由二项式定理可知是 (Theta(3^{log_{2}max{a_{i}}}))。
#include <cstdio>
#define mod ( 1000000007 )
const int MAXN = 250000 + 5;
int N;
int val[MAXN], dp[MAXN];
int buc[MAXN];
int main( ){
scanf( "%d", &N ); for( int i = 1; i <= N; ++ i ){ scanf( "%d", &val[i] ); buc[val[i]] = i; }
int Ans = 0;
for( int i = N; i; -- i ){
dp[i] = 1;
for( int j = val[i] & ( val[i] - 1 ); j; j = ( j - 1 ) & val[i] ){
if( buc[j] > i ) dp[i] = ( dp[i] + dp[buc[j]] ) % mod;
}
Ans = ( Ans + dp[i] ) % mod;
}
printf( "%d
", ( Ans - N + mod ) % mod );
return 0;
}