$ >Codeforces \space 388 D. \ Fox\ and\ Perfect\ Sets<$

题目大意 :

定义一个完美的集合 \(S\) ,当且仅当 \(S\) 非负非空,且 \(\forall a, b \in S, a\text{ xor } b \in S\) ,求集合内最大元素不超过 \(n\) 的完美集合数量

\(1 \leq n \leq 10^9\)

解题思路 :

一个完美的集合等价于某个线性基能表示出的所有元素,所以问题转化为对能表示的最大元素 \(\leq n\) 的线性基计数

考虑一个集合的线性基可能有很多种,但是必然存在一种方案使得基上的二进制位表示出来的元素是最大元素,不妨直接对满足这种特征的线性基计数

考虑某一个二进制位如果在基中,那么基中其他位的数都不能有这个位,反之基中所有比它高的位都的数都可以有这个位

如果不考虑 \(n\) 的限制的话,可以得出一个简单的 \(dp[i][j]\) 表示从高到低第 \(i\) 个二进制位,已经选了 \(j\) 个二进制位作为基的方案数

根据上面推导可以得到 \(dp[i][j] = dp[i-1][j] \times 2^j + dp[i-1][j-1]\) (选这位为基/不选)

实际上如果有 \(n\) 的限制的话,是要满足有 \(1\) 的二进制位组成的二进制数不能超过 \(n\) ,可以直接套一个数位 \(dp\)

具体的说,\(dp[i][j][0/1]\) 表示从高到低第 \(i\) 个二进制位,已经选了 \(j\) 个二进制位作为基,当且有 \(1\) 的位是否是 \(n\) 在二进制下的前缀

根据当前 \(n\) 的二进制位是 \(0\) 还是 \(1\) 分讨转移即可

/*program by mangoyang*/
#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
} #define int ll
const int Mod = 1e9+7;
int s[55], f[55][55][2], len, ans;
inline void up(int &x, int y){ x = (x + y % Mod) % Mod; }
signed main(){
int x; read(x); if(!x) s[++len] = 0;
while(x) s[++len] = x % 2, x /= 2;
reverse(s + 1, s + len + 1);
f[0][0][1] = 1;
for(int i = 1; i <= len; i++)
for(int j = 0; j <= len; j++){
if(j) up(f[i][j][0], f[i-1][j-1][0]);
up(f[i][j][0], f[i-1][j][0] * (1ll << j));
int x = (j ? (1ll << j - 1) : 1) % Mod;
int y = (j ? (1ll << j - 1) : 0) % Mod;
if(s[i] == 0) up(f[i][j][1], f[i-1][j][1] * x);
else{
if(j) up(f[i][j][1], f[i-1][j-1][1]);
up(f[i][j][1], f[i-1][j][1] * y);
up(f[i][j][0], f[i-1][j][1] * x);
}
}
for(int i = 0; i <= len; i++)
up(ans, f[len][i][0]), up(ans, f[len][i][1]);
cout << ans;
return 0;
}

最新文章

  1. 【MCU】【STM32】1.cube MX库使用笔记
  2. On One Side Kolmogorov Type Inequalities
  3. 基于TCP和多线程实现无线鼠标键盘-Socket(1)
  4. 【背景建模】SACON
  5. Eclipse 快捷键 自动生成get/set注释(转)
  6. 主DNS配置
  7. SQL查询语句去除重复行
  8. Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include
  9. cocos2dx游戏资源加密之XXTEA
  10. FPGA开发(2)
  11. bash shell中测试命令
  12. C语言实现二叉树的基本操作
  13. ajax文件上传-FormData()
  14. SimInfo获取(MCC, MNC, PLMN)
  15. Leetcode--680. Valid Palindrome II(easy)
  16. C#中分别对委托、匿名方法、Lambda表达式、Lambda表达式树以及反射执行同一方法的过程进行比较。
  17. dojo学习(一)入门
  18. ECU
  19. 通过openresty && tengine && nginx 动态添加资源到 html 页面
  20. [转] ScalaTest测试框架

热门文章

  1. LintCode 539: Move Zeroes
  2. Oracle解锁scott账户
  3. Javascript装饰器的妙用
  4. linux的curl用法【转】
  5. 数学中的Sin和Cos是什么意思?(转)
  6. 5、SourceTree使用git
  7. tomcat已启动,使用maven的deploy发布后,根据路径打开浏览器访问时报错HTTP Status 500 - Error instantiating servlet class
  8. 以太坊go-ethereum客户端docker安装(一)
  9. 这是我在word 2010上发布的第一篇文章
  10. 1-4 TCP/IP协议族