我们可以知道异或可以看成不进位的加法,那么我们就可以得到 \(a + b = a\) ^ \(b + ((a \& b) << 1)\),不难发现 \(\frac{v - u}{2}\) 就是 \(a \& b\) 也就是 \(a, b\) 中同时为 \(1\) 的位置,那么只需要满足 \(\frac{v - u}{2} \& u = 0\) 且 \((i - j) \% 2 = 0\)我们就能合理分配 \(a, b\) 的 \(0 / 1\) 使得 \(u, v\) 能够被表示出来。于是我开始从 \(u, v\) 的判定条件入手,枚举 \(u\) 然后可以从最高位往下做一个 \(dp\) 这样就可以做到 \(O(n \log n)\) 但想了很久都没办法继续优化下去了。

当我们陷入死胡同的时候,不妨走出来换一个方向再继续。因为 \(a + b = v \le n\) 因此我们可以直接考虑枚举这样的 \((a, b)\) 来判定哪些 \((u, v)\) 是合法的,于是我们有了这样一个想法,我们能否将问题转化成统计一些合法的 \((a, b)\) 以知道 \((u, v)\) 的数量呢?实际上我们可以考虑一对合法的 \((u, v)\) 可以被那些 \((a, b)\) 表示出来,我们单独考虑 \(u\) 的二进制位,如果这个位置上是 \(1\) 那么就表示 \(a, b\) 在这一位上有一个是 \(1\) 另一个是 \(0\),如果是 \(u\) 在这一位上是 \(0\) 就表示 \((a, b)\) 在这一位上要么都是 \(1\) 要么都是 \(0\),可以发现因为 \(a + b = v\) 是确定的,因此都是 \(1\) 和都是 \(0\) 的位置是确定的,那么同一对 \((u, v)\) 能被不同的 \((a, b)\) 表示出来当且仅当 \((a, b)\) 在某一位上一个是 \(1\) 一个是 \(0\),因此我们在统计这样 \((a, b)\) 时可以钦定 \(a\) 的每一位都不大于 \(b\),这样就能不重不漏地统计完所有答案了。

于是原问题被我们转化为,统计二元组 \((a, b)\) 的数量满足 \(0 \le a \le b \le n, a + b \le n\) 且在二进制位下 \(a\) 的每一位都不大于 \(b\)。于是我们可以考虑令 \(dp_i\) 表示 \(a + b \le i\) 的合法二元组数量,因为要满足二进制位下 \(a\) 的每一位不大于 \(b\),因此我们在考虑往 \(a, b\) 末尾同时加入一个数时只可能是 \((0, 0) / (0, 1) / (1, 1)\),对应着转移就是 \(dp_i = dp_{\lfloor \frac{i}{2} \rfloor} + dp_{\lfloor \frac{i - 1}{2} \rfloor} + dp_{\lfloor \frac{i - 2}{2} \rfloor}\)。可以用记忆化搜索实现这个过程,可以发现每次往下递归时要求的 \(dp\) 值实际上只有两个,如果 \(i = 2k + 1\) 且 \(k\) 为奇数时我们恰好发现下面需要求的 \(dp\) 值又只有一边,如果 \(k\) 为偶数可以发现最多经过 \(\log n\) 次就会变成 \(k\) 为奇数的情况,而每次除了 \(\frac{k}{2}\) 的部分最多往下多算两次,而最开始 \(i = 2k\) 时与这里类似,因此我们有效的合法状态大约是 \(O(3 \log n)\) 的,实际上效率非常高,有效状态在 \(O(2 \log n) \sim O(3 \log n)\) 之间。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define Mod 1000000007
#define rep(i, l, r) for(int i = l; i <= r; ++i)
int n, cnt;
unordered_map <int, int> dp;
int read(){
char c; int x = 0, f = 1;
c = getchar();
while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int Inc(int a, int b){
return (a += b) >= Mod ? a - Mod : a;
}
int dfs(int n){
if(dp[n]) return dp[n];
return dp[n] = Inc(Inc(dfs(n / 2), dfs((n - 1) / 2)), dfs((n - 2) / 2));
}
signed main(){
n = read(), dp[0] = 1, dp[1] = 2;
printf("%lld\n", dfs(n));
return 0;
}

可以发现因为是递推式,其实我们可以打表看出规律,但这个递推式有点刁钻,也可能是我太弱了吧。以后这种二进制下满足某种条件的数的个数递推式可以考虑在 \(\lfloor \frac{i}{2} \rfloor\) 附近的值考虑。

AT2272 [ARC066B] Xor Sum的更多相关文章

  1. AT2272 [ARC066B] Xor Sum 题解

    题目连接:传送门 分析 这道题只看题目中给的样例是找不出规律的 所以我们可以打一下表 1, 2, 4, 5, 8, 10, 13, 14, 18 如果你还是没有看出什么规律的话,我们可以从OEIS上搜 ...

  2. HDU 4825 Xor Sum(经典01字典树+贪心)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total ...

  3. 字典树-百度之星-Xor Sum

    Xor Sum Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包括了N个正整数,随后 Prometheu ...

  4. HDU 4825 Xor Sum 字典树+位运算

    点击打开链接 Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) ...

  5. 2014百度之星第三题Xor Sum(字典树+异或运算)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total ...

  6. Xor Sum 01字典树 hdu4825

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total S ...

  7. hdu 4825 Xor Sum (01 Trie)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题面: Xor Sum Time Limit: 2000/1000 MS (Java/Others) ...

  8. HDU--4825 Xor Sum (字典树)

    题目链接:HDU--4825 Xor Sum mmp sb字典树因为数组开的不够大一直wa 不是报的 re!!! 找了一下午bug 草 把每个数转化成二进制存字典树里面 然后尽量取与x这个位置上不相同 ...

  9. hdu 4825 Xor Sum trie树

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Proble ...

随机推荐

  1. Mysql数据库体系

    Mysql数据库体系如下(手绘): 描述: 1.DBMS:database system management是数据库管理软件,平时我们使用的数据库的全称,是C/S架构(client/server)工 ...

  2. CapstoneCS5210|CS5210低BOM成本方案CS5210|HDMI转VGA芯片方案

    Capstone最新推出的一款HDMI转VGA音视频转接线或者转换器方案芯片CS5210. 其设计的优势在于内置晶振,外围电路器件较少设计简单,芯片封装集成度较高,方案BOM成本低,相比其他方案产品更 ...

  3. JUC之线程间定制化通信

    线程通信之定制化 之前文章中写了下Condition的使用,这里我们详细说下其中的用法: 首先使用Condition需要实例化Lock private Lock lock = new Reentran ...

  4. 编写Java程序,使用JTable表格组件展现人员信息列表

    返回本章节 返回作业目录 需求说明: 使用JTable组件显现人员信息列表 实现思路: 创建一个JTable对象. 创建一个JScrollPane对象(显示横向和纵向滚动条). 将表格添加到滚动面板. ...

  5. VUE的学习_从入门到放弃(一)

    一.vue的功能及作用 工作方式如下 1.不用操作DOM 2.单页面应用web项目 简称:SPA 3.当下各种新框架都采用的类似Vue或者类似React的语法去作为主语法,微信小程序/MpVue... ...

  6. SpringCloud创建Config读取本地配置

    1.说明 Config Server获取配置支持的方式很多, 包括Git仓库(github/gitee等),任何与JDBC兼容的数据库, Subversion,Hashicorp Vault,Cred ...

  7. Selenium_使用switch_to.alert处理弹窗(14)

    与switch_to.window 和 switch_to.frame 相比,switch_to.alert的alert方法使用了@property 装饰器,所以在使用时alert被当成属性调用. 演 ...

  8. [ flask-migrate ] 记自己犯的一次低级错误

    问题描述 从github上pull了别人的项目学习,项目用flask-migrate来迁移数据库.查看了一下,作者把数据库文件 app.db 删除了,不过migrations文件夹留着的,因此我只需要 ...

  9. spring security 关于 http.sessionManagement().maximumSessions(1);的探究

    1.前言 spring security 支持对session的管理 , http.sessionManagement().maximumSessions(1);的意思的开启session管理,ses ...

  10. Word2010制作自动目录

    原文链接:https://www.toutiao.com/i6488296610873737741/ 原文从网上复制: 查看"开始"选项卡,"样式"功能组,我们 ...