Solution -「洛谷 P3773」「CTSC 2017」吉夫特
§ Description
Link.
求满足
∏i=2k(abiabi−1)mod2=(ab2ab1)×(ab3ab2)×⋯(abkabk−1)mod2>0
的子序列个数。
§ Solution
哇哦。
i=2∏k(abiabi−1)≡i=2∏k(⌊2abi⌋⌊2abi−1⌋)×(abimod2abi−1mod2)(mod2)
式子后面的 (abimod2abi−1mod2) 一共有四种情况,其中只有 (10)=0。其他都为 1。
意味着只要出现 abi−1≡0mod2 且 abi≡1mod1 的情况,整个式子就为零了。
结论:(mn)≡0 (mod2) 当且仅当 nbitandm=m。
证明(也许不是特别严谨):我们可以知道:
(mn)=(⌊2m⌋⌊2n⌋)×(mmod2nmod2)=(⌊2⌊2m⌋⌋⌊2⌊2n⌋⌋)×(⌊2m⌋mod2⌊2n⌋mod2)×(mmod2nmod2)=⋯
我们发现:
(⌊⋯⌊2⌊2m⌋⌋⌋⌊⋯⌊2⌊2n⌋⌋⌋)
这一坨,就是在一直进行二进制移位,shr1。
那么我们可以得出一个结论:如果对于我们记 (n)k 表示 n 在二进制意义下的第 k 位。(n)k∈[0,1]
那么对于 ∀i,有 (n)i=0 且 (m)i=1,那么 (mn)≡0 (mod2)。
所以 nbitandm=m,证毕。
我们题目要求的是最后算出来是个奇数,那么就不能存在 abi−1bitandabi=abi。
也就是 abi 为 abi−1 的子集。
接下来我们可以设计一个 DP,我们设 fi 为以 ai 为开头的答案。
那么转移就是加法原理:
fi=fi+fj,j∈ai∧tj>i
其中 ti 表示 i 在序列中的位置。
时间复杂度由二项式定理可知是 Θ(3log2max{ai})。
#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\n", ( Ans - N + mod ) % mod );
return 0;
}