Problem
【CTSC2017】吉夫特
时间限制: 2 S e c \mathrm{2\;Sec} 2 S e c
空间限制: 256 M B \mathrm{256\;MB} 2 5 6 M B
简单的题目,既是礼物,也是毒药。
B 君 \mathrm{B君} B 君 设计了一道简单的题目,准备作为 g i f t \mathrm{gift} g i f t 送给大家。
输入一个长度为 n n n 的数列 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a 1 , a 2 , … , a n
问有多少个长度大于等于 2 的不上升的子序列 a b 1 , a b 2 , … , a b k a_{b_1}, a_{b_2}, \ldots ,a_{b_k} a b 1 , a b 2 , … , a b k 满足
∏ i = 2 k ( a b i − 1 a b i ) m o d 2 = ( a b 1 a b 2 ) × ( a b 2 a b 3 ) × ⋯ × ( a b k − 1 a b k ) m o d 2 > 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 ∏ i = 2 k ( a b i a b i − 1 ) m o d 2 = ( a b 2 a b 1 ) × ( a b 3 a b 2 ) × ⋯ × ( a b k a b k − 1 ) m o d 2 > 0
输出这个个数对 1000000007 1000000007 1 0 0 0 0 0 0 0 0 7 取模的结果。
输入格式
第一行一个整数 n n n 。
接下来 n n n 行,每行一个整数,这 n n n 行中的第 i i i 行,表示 a i a_i a i 。
输出格式
一行一个整数表示答案。
样例输入输出
样例一
Input
Output
样例二至样例九
见样例数据下载。
限制与约定
对于前 10 % 10\% 1 0 % 的测试点,n ≤ 9 , 1 ≤ a i ≤ 13 n \leq 9, 1 \leq a_i \leq 13 n ≤ 9 , 1 ≤ a i ≤ 1 3 ;
对于前 20 % 20\% 2 0 % 的测试点,n ≤ 17 , 1 ≤ a i ≤ 20 n \leq 17, 1 \leq a_i \leq 20 n ≤ 1 7 , 1 ≤ a i ≤ 2 0 ;
对于前 40 % 40\% 4 0 % 的测试点,n ≤ 1911 , 1 ≤ a i ≤ 4000 n \leq 1911, 1 \leq a_i \leq 4000 n ≤ 1 9 1 1 , 1 ≤ a i ≤ 4 0 0 0 ;
对于前 70 % 70\% 7 0 % 的测试点,n ≤ 2017 n \leq 2017 n ≤ 2 0 1 7 ;
对于前 85 % 85\% 8 5 % 的测试点,n ≤ 100084 n \leq 100084 n ≤ 1 0 0 0 8 4 ;
对于 100 % 100\% 1 0 0 % 的测试点, 1 ≤ n ≤ 211985 , 1 ≤ a i ≤ 233333 1 \leq n \leq 211985, 1 \leq a_i \leq 233333 1 ≤ n ≤ 2 1 1 9 8 5 , 1 ≤ a i ≤ 2 3 3 3 3 3 。
所有的 a i a_i a i 互不相同,也就是说不存在 i , j i,j i , j 同时满足 1 ≤ i < j ≤ n 1 \leq i < j \leq n 1 ≤ i < j ≤ n 和 a i = a j a_i=a_j a i = a j 。
下载
样例数据下载
标签:子集DP
Solution
由L u c a s \mathrm{Lucas} L u c a s 定理可以推得( n m ) ≡ 1 m o d 2 \binom{n}{m}\equiv1\bmod{2} ( m n ) ≡ 1 m o d 2 当且仅当n & m = m n\&m=m n & m = m ,于是原题转为需要使a b i & a b i + 1 = a b i + 1 a_{b_i}\&a_{b_{i+1}}=a_{b_{i+1}} a b i & a b i + 1 = a b i + 1 ,即a b i a_{b_i} a b i 是a b i + 1 a_{b_{i+1}} a b i + 1 的子集。
显然有D P \mathrm{DP} D P :令f [ i ] f[i] f [ i ] 表示在a i a_i a i 后面接若干个a a a 满足条件的序列总数,那么对于a a a 值是当前a i a_i a i 的子集的所有位置j j j ,均有f [ j ] = f [ j ] + f [ i ] f[j]=f[j]+f[i] f [ j ] = f [ j ] + f [ i ] 。直接做子集D P \mathrm{DP} D P 即可。
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 ; }