UOJ300【CTSC2017】吉夫特 <子集DP>

Problem

【CTSC2017】吉夫特

时间限制:2  Sec\mathrm{2\;Sec}
空间限制:256  MB\mathrm{256\;MB}
简单的题目,既是礼物,也是毒药。
B\mathrm{B君}设计了一道简单的题目,准备作为 gift\mathrm{gift} 送给大家。
输入一个长度为 nn 的数列 a1,a2,,ana_1, a_2, \ldots, a_n
问有多少个长度大于等于 2 的不上升的子序列 ab1,ab2,,abka_{b_1}, a_{b_2}, \ldots ,a_{b_k} 满足
i=2k(abi1abi)mod2=(ab1ab2)×(ab2ab3)××(abk1abk)mod2>0\prod_{i = 2}^k \binom{a_{b_{i-1}}}{a_{b_i}} \bmod 2= \binom{a_{b_1}}{a_{b_2}} \times \binom{a_{b_2}}{a_{b_3}} \times \cdots \times \binom{a_{b_{k-1}}}{a_{b_k}} \bmod 2 > 0
输出这个个数对 10000000071000000007 取模的结果。

输入格式

第一行一个整数 nn
接下来 nn 行,每行一个整数,这 nn 行中的第 ii 行,表示 aia_i

输出格式

一行一个整数表示答案。

样例输入输出

样例一

Input

1
2
3
4
5
4
15
7
3
1

Output

1
11

样例二至样例九

见样例数据下载。

限制与约定

对于前 10%10\% 的测试点,n9,1ai13n \leq 9, 1 \leq a_i \leq 13
对于前 20%20\% 的测试点,n17,1ai20n \leq 17, 1 \leq a_i \leq 20
对于前 40%40\% 的测试点,n1911,1ai4000n \leq 1911, 1 \leq a_i \leq 4000
对于前 70%70\% 的测试点,n2017n \leq 2017
对于前 85%85\% 的测试点,n100084n \leq 100084
对于 100%100\% 的测试点, 1n211985,1ai2333331 \leq n \leq 211985, 1 \leq a_i \leq 233333
所有的 aia_i 互不相同,也就是说不存在 i,ji,j 同时满足 1i<jn1 \leq i < j \leq nai=aja_i=a_j

下载

样例数据下载

标签:子集DP

Solution

Lucas\mathrm{Lucas}定理可以推得(nm)1mod2\binom{n}{m}\equiv1\bmod{2}当且仅当n&m=mn\&m=m,于是原题转为需要使abi&abi+1=abi+1a_{b_i}\&a_{b_{i+1}}=a_{b_{i+1}},即abia_{b_i}abi+1a_{b_{i+1}}的子集。
显然有DP\mathrm{DP}:令f[i]f[i]表示在aia_i后面接若干个aa满足条件的序列总数,那么对于aa值是当前aia_i的子集的所有位置jj,均有f[j]=f[j]+f[i]f[j]=f[j]+f[i]。直接做子集DP\mathrm{DP}即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <bits/stdc++.h>
#define MAX_A 233333
#define P 1000000007
using namespace std;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
int n, s, f[MAX_A+5];
int main() {
read(n);
for (int i = 1, x, t; i <= n; i++) {
read(x), t = (f[x]+1)%P, (s += t) %= P;
for (int y = x; y; y = (y-1)&x)
(f[y] += t) %= P;
}
return printf("%d\n", s-n), 0;
}