卧薪尝胆,厚积薄发。
sequence
Date: Mon Mar 04 14:35:15 CST 2019
In Category:
NoCategory
Description:
给出一个序列
$a$
,求所有
$\prod\binom{b_k}{b_{k+1}}\bmod 2=1$
的子序列
$b$
的个数。
$1\leqslant n\leqslant 10^5$
Solution:
不难发现是
$CTSC$
吉夫特加强版。
首先根据卢卡斯定理:
$$
\binom nm\bmod2=\binom{n/2}{m/2}\bmod2\times \binom{n\bmod 2}{m\bmod2}\bmod2
$$
然后就会发现,这样的子序列满足后一个是前一个的子集,于是可以暴力
$DP$
,每次枚举子集转移,但是由于这题不保证数字两两不同,因此复杂度是
$O(n2^n)$
的。
考虑值域分块,也就是设
$f[i][j]$
表示前
$9$
位是
$i$
的子集,后
$9$
位是
$j$
的方案数,然后就会发现枚举量只有
$2^9$
可以通过。时间复杂度
$O(2^9n)$
。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n;
#define MAXN 100010
#define N 200010
int a[MAXN];
int f[1 << 9][1 << 9];
#define P 998244353
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
int ans = 0;
memset(f,0,sizeof(f));
for(int i = n;i >= 1;--i)
{
int v = a[i] & ((1 << 9) - 1);
int top = a[i] >> 9,bot = (a[i] ^ (top << 9));
int val = 0;
for(int j = v;;j = (j - 1) & v)
{
val = (val + f[top][j]) % P;
if(j == 0)break;
}
v = ((1 << 9) - 1) ^ top;
val = (val + 1) % P;
for(int j = v;;j = (j - 1) & v)
{
f[j ^ top][bot] = (f[j ^ top][bot] + val) % P;
if(j == 0)break;
}
}
for(int i = 0;i < (1 << 9);++i)ans = (ans + f[(1 << 9) - 1][i]) % P;
cout << (ans - n + P) % P << endl;
return 0;
}
In tag:
数学-组合数学-卢卡斯定理 数据结构-根号分治
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡