题目链接

首先\(C(n,m)\)为奇数当且仅当\(n\&m=m\)。

简要证明: 因为是\(mod\ 2\),考虑Lucas定理。

在\(mod\ 2\)的情况下\(C(n,m)\)最后只会化成4种情况:\(C(0,1),C(0,0),C(1,0),C(1,1)\)。

后三种情况都是1,\(C(0,1)\)不存在(=0)。所以如果\(C(n,m)mod\ 2\)为偶数,那么在Lucas的过程中一定出现了\(C(0,1)\)。

\(mod\ 2\)的过程容易想到位运算。

由\(C(n,m)mod\ 2=C(n\%2,m\%2)*C(n/2,m/2)=C(n\&1,m\&1)*C(n>>1,m>>1)\)

可知,若\(C(n,m)\)为奇数,那么\(m\)一定是\(n\)二进制1的子集(否则存在\(C(0,1)\))。

因为要满足\(n\&m=m\),所以题意即为,有多少个\(a\)的子序列\(b\),满足\(b_i\&b_{i+1}=b_{i+1}\)。

令\(f[i]\)表示以\(A[i]\)结尾的合法子序列数。

那么有两种显然的方式:

  1. 枚举\(i\),\(ans+=f[i]\),再更新后面满足 \(A[j]\)的二进制位是\(A[i]\)二进制位的子集 的\(j\),\(f[j]+=f[i]\)。
  2. 枚举\(i\),枚举\(j\),求\(f[i]=\sum_{j<i,A[j]是A[i]的超集}f[j]\),然后\(ans+=f[i]\)。

两种都是枚举子集。第一种是不需要查询,转移\(O(3^{18})\);第二种是查询\(O(3^{18})\),不需要转移。

(整个算法实际上是对每个\(a_i\)的二进制表示枚举了它的子集,而\(a_i\)互不相同,相当于是对所有二进制子集枚举了它的子集,所以复杂度是\(3^{\log a_{max}}=3^{18}\))

这样好像比较危险?(出二进制\(1\)很多的\(a_i\))


(以上都不是重点)

我们将这两种方式综合一下:

转移时,固定\(i\)的后\(9\)位,枚举\(i\)前\(9\)位的子集\(j\),用\(f[i]\)更新后面的\(f[j]\);

求值时,固定\(i\)的前\(9\)位,枚举\(i\)后\(9\)位的超集\(j\),从前面的\(f[j]\)转移,即\(f[i]=\sum f[j]\)。

这样复杂度是啥啊。。我不知道,反正靠谱很多。

dls现场分析:大概是从之前的\(2^{\log_23\cdot n}=2^{1.59n}\)优化到了\(2^{1.5n}\)。

考虑枚举不满,大概有\(2^{(0.6+\frac{1.59}{2})n}=2^{1.3n+}\)?


顺便记下枚举子集复杂度\(O(3^n)\)的证明:

证明:设集合有\(n\)个元素,我们把所有子集\(s\)按元素个数\(k=|s|\)分类(因为它们的子集都为\(2^k\)个。那么枚举的集合数为:$$\sum_{k=0}nC_{n}k2k=(1+2)n=3^n$$

代码就是这样:

for(s=0; s<all; ++s)
for(i=s; i; i=(i-1)&s)
...

以前的题解(naive啊):https://www.cnblogs.com/SovietPower/p/8776368.html。


//3800kb	688ms
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 2000000
#define mod 1000000007
#define Mod(x) x>=mod&&(x-=mod)
typedef long long LL;
const int N=(1<<18)+3,L=(1<<9)-1; struct io
{
char IN[MAXIN],*s;
io():s(IN) {IN[fread(IN,1,MAXIN,stdin)]=0;}
inline operator int()
{
int x=0;
for(; *s<48; ++s);
for(; *s>47; x=x*10+*s++-48);
return x;
}
}io; int main()
{
static int f[N];
int n=io; LL ans=0,sum;
for(int i=1,a; i<=n; ++i)
{
a=io,sum=0;
int l=a&L, r=a>>9;
for(int j=r; j<=L; j=(j+1)|r)
sum+=f[(j<<9)|l];
ans+=sum%=mod, ++sum;
r<<=9;
for(int j=l; j; j=(j-1)&l)
f[j|r]+=sum, Mod(f[j|r]);
f[r]+=sum, Mod(f[r]);//0|r
}
printf("%lld\n",ans%mod); return 0;
}

BZOJ.4903.[CTSC2017]吉夫特(Lucas DP)的更多相关文章

  1. BZOJ 4903: [Ctsc2017]吉夫特 数论+dp

    思路很巧妙的一道题 ~ 这个应该不完全是正解,复杂度约为 $O(3\times 10^8)$,有时间再研究研究正解. 首先,最裸的暴力是按照权值从小到大枚举每一个数,然后枚举后面的数来更新方案数,是 ...

  2. bzoj 4903: [Ctsc2017]吉夫特【lucas+状压dp】

    首先根据lucas, \[ C_n^m\%2=C_{n\%2}^{m\%2}*C_{n/2}^{m/2} \] 让这个式子的结果为计数的情况只有n&m==m,因为m的每一个为1的二进制位都需要 ...

  3. [CTSC2017]吉夫特(Lucas定理,DP)

    送70分,预处理组合数是否为偶数即可. 剩下的数据,根据Lucas定理的推论可得当且仅当n&m=n的时候,C(n,m)为奇数.这样就可以直接DP了,对于每个数,考虑它对后面的数的影响即可,直接 ...

  4. 洛谷P3773 [CTSC2017]吉夫特(Lucas定理,dp)

    题意 满足$b_1 < b_2 < \dots < b_k$且$a_{b_1} \geqslant a_{b_2} \geqslant \dots \geqslant a_{b_k} ...

  5. bzoj4903 & loj2264 [Ctsc2017]吉夫特 Lucas 定理+状压DP

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4903 https://loj.ac/problem/2264 http://uoj.ac/pr ...

  6. uoj 300 [CTSC2017]吉夫特 - Lucas - 分块 - 动态规划

    题目传送门 戳此处转移 题目大意 给定一个长为$n$的序列,问它有多少个长度大于等于2的子序列$b_{1}, b_{2}, \cdots, b_{k}$满足$\prod_{i = 2}^{k}C_{b ...

  7. BZOJ4903 UOJ300 CTSC2017 吉夫特 【Lucas定理】

    BZOJ4903 UOJ300 CTSC2017 吉夫特 弱弱地放上题目链接 Lucas定理可以推一推,发现C(n,m)是奇数的条件是n" role="presentation&q ...

  8. [BZOJ 4033] [HAOI2015] T1 【树形DP】

    题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...

  9. Bzoj 1055: [HAOI2008]玩具取名 (区间DP)

    Bzoj 1055: [HAOI2008]玩具取名 (区间DP) 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1055 区间动态规划和可 ...

随机推荐

  1. Sql 插入自定义主键

    在遇到数据库设计是自增的主键,且需要插入自定义的主键Id时,这个时候如果直接Insert的话,将会发生错误,错误提示信息: 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'XXX' ...

  2. Android数据存储:Shared Preferences

    Android数据存储之SharedPreferences 在Android系统中提供了多种存储技术.通过这些存储技术可以将数据存储在各种存储介质上, Android 为数据存储提供了如下几种方式:1 ...

  3. Expm 4_2 有向无环图中的最短路径问题

    [问题描述] 建立一个从源点S到终点E的有向无环图,设计一个动态规划算法求出从S到E的最短路径值,并输出相应的最短路径. 解: package org.xiu68.exp.exp4; import j ...

  4. MySQL 命令行工具不能向表中插入中文的解决方法

    1.报错图示 解释:sname这个字段 解析出错. 2.解决方法 打开MySQL的安装目录,找到my.ini文件,把57和81行的utf8改成gbk后 保存,最后,重启MySQL的服务 即可. 3.测 ...

  5. 【gearman】学习笔记

    学习资料:http://gearman.org/manual/ 1.Gearman是跨语言的,client和worker可以用不同的语言来实现 2.client与job server之间的交互称为ta ...

  6. js中常见的数组排序算法-冒泡排序和选择排序

    reverse( )  数组逆序   // reverse() 数组逆序 var arr = ["边境牧羊犬", "德国牧羊犬", "金毛" ...

  7. python3 + selenium 运行过程中进行截图

    使用driver.get_screenshot_as_file方法("D:/aaac.png")括号中为需要存放的路径及图片名称 from selenium import webd ...

  8. java / android int类型如何判空?

    /** TextUtils.isEmpty() 方法的实现 * Returns true if the string is null or 0-length. * @param str the str ...

  9. Nginx 响应状态

    ngx.status = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release)ngx.status = ngx.HTTP_SWITC ...

  10. Swagger 常用注解

    一.Swagger常用注解 1.与模型相关的注解 两个注解: @ApiModel:用在模型类上,对模型类做注释: @ApiModelProperty:用在属性上,对属性做注释 2.与接口相关的注解 六 ...