手动博客搬家: 本文发表于20181105 23:18:54, 原地址https://blog.csdn.net/suncongbo/article/details/83758728

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=3329

思路分析:

这道题完全是两道题拼在了一起。。

我们首先观察一下这个等式:

我们不妨可以把它移项变成\(x\ xor\ (2x)=3x\)

然后我们发现,\(3x=x+2x\), 也就是\(x\ xor\ (2x)=x+2x\).

并且显然有不等式\(|x-y|\le x\ and\ y\le x \ xor\ y\le x \ or\ y\le x+y\), 故有\(x\ or\ 2x=x+2x\), 也即\(x\ and\ 2x = 0\).

这意味着什么?我们考虑一个\(x\):

  1. x = 00110111001010111010100111011
  2. 2x = 01101110010101110101001110110
  3. x^2x = 01011001011111001111101001101

观察可得,\(x\ xor\ 2x\)相当于将二进制表示作了异或差分。同时,所有相邻的\(1\)只会保留最后一个和第一个的前一个,而中间这一部分都会被变成\(0\). 因此,题目中的等式成立等价于\(x\)的二进制表示下不存在相邻的\(1\).

另一种理解方式是:异或相当于二进制不进位加法,而既然是不进位加法,那么一旦进了位就会对数值有损失,当且仅当\(x+2x\)不进位的时候它才等于\(x\ xor\ 2x\). 而\(2x\)相当于把\(x\)的二进制表示左移一位,进位发生当且仅当\(x\)与\(2x\)在同一位置上都为\(1\),也即\(x\)有连续的至少两个\(1\).

完成了这一步转化之后,问题就相当于求\(n\)或者\(2^n\)内有多少数的二进制表示下不存在两个连续的\(1\).

第二问

\([0,2^n-1]\)之内的数对应长度为\(n\)的\(01\)序列,不能有连续两个\(1\), 这显然是斐波那契数列。(因为有一种进制叫斐波那契进制,有一个定理是任何一个整数都可以被唯一地划分成若干不连续的斐波那契数之和)严谨一些的证明是,设\(F(n)\)表示长度为\(n\)的满足条件的\(01\)序列有多少个,则\(F(n)\)如果第一位为\(1\), 那么第二位必然为\(0\), 后面\(n-2\)位方案数\(F(n-2)\); 如果第一位为\(0\), 那么后面的位任选,方案数\(F(n-1)\). 因此\(F(n)=F(n-1)+F(n-2)\).

但是我们刚才讨论的是\([0,2^n-1]\), 但题目要求的是\([1,2^n]\), 显然\(0\)必定满足条件,\(2^n\)也必定满足条件,因此答案为\(F(n)-1+1=F(n)\).

用矩快速幂递推即可,时间复杂度\(O(\log n)\), \(8\)倍常数。

第一问

这一问对\(n\)有更细致的要求,每一位都有要求,因此采取数位\(dp\).

设\(dp[i][j=0/1][k=0/1]\)表示有多少个\(i\)位数 (\([0,2^i-1]\))满足条件,且第\(i\)位是否必须选\(0\) (即如果\(j\)为\(1\)则必须选\(0\), 否则选\(0,1\)均可),\(k\)表示是否卡上界。考虑转移,这一位能够选\(1\)的条件是,\(j\)是\(false\), 并且选了\(1\)之后不会超过\(n\)的限制。超过\(n\)的限制的充要条件是,当前卡上界,且\(n\)这一位为\(0\). 这一位选\(0\)无条件转移。于是就可以成功DP了,时间复杂度\(O(\log n)\), 常数\(4\)倍。

(但是由于蒟蒻太傻,写代码的时候用了大量的(!(n&(1<<(pos-1))))来判断\(n\)这一位是否为\(0\), 因此代码十分丑陋,有的地方\(7\)层括号套起来。。希望读者见谅)

代码实现
  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define llong long long
  6. #define ldouble long double
  7. #define uint unsigned int
  8. #define ullong unsigned long long
  9. #define udouble unsigned double
  10. #define uldouble unsigned long double
  11. #define modinc(x) {if(x>=P) x-=P;}
  12. #define pii pair<int,int>
  13. #define piii pair<pair<int,int>,int>
  14. #define piiii pair<pair<int,int>,pair<int,int> >
  15. #define pli pair<llong,int>
  16. #define pll pair<llong,llong>
  17. #define Memset(a,x) {memset(a,x,sizeof(a));}
  18. using namespace std;
  19. llong n;
  20. namespace Subtask1
  21. {
  22. const int N = 60;
  23. llong dp[N+2][2][2];
  24. llong dfs(int pos,bool f,bool t)
  25. {
  26. // printf("DFS %d %d %d %lld\n",pos,(int)f,(int)t,dp[pos][f][t]);
  27. if(pos==1) return dp[pos][f][t] = 1ll+(f==false && (!(t&&(!(n&(1ll<<(pos-1)))))));
  28. if(dp[pos][f][t]) return dp[pos][f][t];
  29. llong cur = dfs(pos-1,false,(t&&(!(n&(1ll<<(pos-1))))));
  30. if(f==false && (!(t&&(!(n&(1ll<<(pos-1))))))) cur += dfs(pos-1,true,t);
  31. // printf("dfs %d %d %d %lld\n",pos,(int)f,(int)t,cur);
  32. return dp[pos][f][t] = cur;
  33. }
  34. void solve()
  35. {
  36. memset(dp,0,sizeof(dp));
  37. llong ans = dfs(N,false,true);
  38. printf("%lld\n",ans-1);
  39. }
  40. }
  41. namespace Subtask2
  42. {
  43. const int N = 3;
  44. const int P = 1e9+7;
  45. struct Matrix
  46. {
  47. llong a[N+2][N+2];
  48. int sz1,sz2;
  49. Matrix() {}
  50. Matrix(int _sz)
  51. {
  52. sz1 = sz2 = _sz;
  53. for(int i=1; i<=sz1; i++)
  54. {
  55. a[i][i] = 1ll;
  56. for(int j=1; j<=sz2; j++)
  57. {
  58. if(i!=j) a[i][j] = 0ll;
  59. }
  60. }
  61. }
  62. void clear()
  63. {
  64. for(int i=1; i<=sz1; i++) for(int j=1; j<=sz2; j++) a[i][j] = 0ll;
  65. }
  66. void setsz(int _sz) {sz1 = sz2 = _sz; clear();}
  67. void setsz2(int _sz1,int _sz2) {sz1 = _sz1,sz2 = _sz2; clear();}
  68. };
  69. Matrix operator *(Matrix m1,Matrix m2)
  70. {
  71. Matrix ret; ret.setsz2(m1.sz1,m2.sz2);
  72. for(int i=1; i<=m1.sz1; i++)
  73. {
  74. for(int j=1; j<=m2.sz2; j++)
  75. {
  76. ret.a[i][j] = 0ll;
  77. for(int k=1; k<=m1.sz2; k++)
  78. {
  79. ret.a[i][j] += m1.a[i][k]*m2.a[k][j];
  80. }
  81. ret.a[i][j] %= P;
  82. }
  83. } return ret;
  84. }
  85. Matrix mquickpow(Matrix x,llong y)
  86. {
  87. Matrix cur = x,ret = Matrix(x.sz1);
  88. for(int i=0; y; i++)
  89. {
  90. if(y&(1ll<<i)) {ret = ret*cur; y-=(1ll<<i);}
  91. cur = cur*cur;
  92. } return ret;
  93. }
  94. void solve()
  95. {
  96. Matrix fib; fib.setsz(2); fib.a[1][1] = fib.a[1][2] = fib.a[2][1] = 1ll; fib.a[2][2] = 0ll;
  97. Matrix ori; ori.setsz2(1,2); ori.a[1][1] = ori.a[1][2] = 1ll;
  98. Matrix gg = ori*fib;
  99. Matrix fibn = ori*mquickpow(fib,n); llong ans = fibn.a[1][1];
  100. printf("%lld\n",ans);
  101. }
  102. }
  103. int main()
  104. {
  105. int T; scanf("%d",&T);
  106. while(T--)
  107. {
  108. scanf("%lld",&n);
  109. Subtask1::solve();
  110. Subtask2::solve();
  111. }
  112. return 0;
  113. }

BZOJ 3329 Xorequ (数位DP、矩阵乘法)的更多相关文章

  1. BZOJ 3329: Xorequ [数位DP 矩阵乘法]

    3329: Xorequ 题意:\(\le n \le 10^18\)和\(\le 2^n\)中满足\(x\oplus 3x = 2x\)的解的个数,第二问模1e9+7 \(x\oplus 2x = ...

  2. BZOJ 3329 Xorequ 数字DP+矩阵乘法

    标题效果:特定n,乞讨[1,n]内[1,2^n]差多少x满足x^3x=2x x^3x=2x相当于x^2x = 3x 和3x=x+2x 和2x=x<<1 因此x满足条件IFFx&(x ...

  3. 【bzoj3329】Xorequ 数位dp+矩阵乘法

    题目描述 输入 第一行一个正整数,表示数据组数据 ,接下来T行每行一个正整数N 输出 2*T行第2*i-1行表示第i个数据中问题一的解, 第2*i行表示第i个数据中问题二的解, 样例输入 1 1 样例 ...

  4. BZOJ 3329 - Xorequ - 数位DP, 矩乘

    Solution 发现 $x \ xor \  2x = 3x$ 仅当 $x$ 的二进制中没有相邻的 $1$ 对于第一个问题就可以进行数位DP 了. 但是对于第二个问题, 我们只能通过递推 打表 来算 ...

  5. BZOJ.3329.Xorequ(数位DP)

    题目链接 x^3x=2x -> x^2x=3x 因为a^b+((a&b)<<1)=a+b,x^2x=x+2x,所以x和2x的二进制表示中不存在相邻的1. (或者,因为x+2x ...

  6. BZOJ 3329: Xorequ(数位dp+递推)

    传送门 解题思路 可以把原式移项得\(x\)^\(2x\)=\(3x\),而\(x+2x=3x\),说明\(x\)二进制下不能有两个连续的\(1\).那么第一问就是一个简单的数位\(dp\),第二问考 ...

  7. bzoj 3329: Xorequ【数位dp+矩阵乘法】

    注意第一问不取模!!! 因为a+b=a|b+a&b,a^b=a|b-a&b,所以a+b=a^b+2(a&b) x^3x==2x可根据异或的性质以转成x^2x==3x,根据上面的 ...

  8. 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

    挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...

  9. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

随机推荐

  1. Handler类和Handler,Loop,MessageQueue的工作原理

    原文地址:http://blog.csdn.net/xiyangyang8/article/details/50754771 Handler类的作用主要有两种: 1.在新启动的线程中发送消息. 2.在 ...

  2. CSS3:box-sizing:不再为盒子模型而烦恼

    题外话: W3C奉行的标准,就是content-box,就是须要计算边框,填充还有内容的;可是就我个人而言, 比較喜欢的是传统IE6时候的怪异模式,不用考虑容器是否会被撑开(打乱布局); 盒子模型差异 ...

  3. 在Win7中修改 系统盘中 “系统” - “用户” 的环境变量映射关系

    1.在此列表中,选中对应登录帐号 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList 2.将Prof ...

  4. TCP打开文件传输(客户端code)

    #include <stdio.h>#include <stdlib.h>#include <arpa/inet.h>#include <sys/types. ...

  5. 快速排序及三向切分快排——java实现

    快速排序也是一种分治算法.主要思想是选取一个切分点,将大于切分点的元素都放置到数组右侧,小于切分点的元素都放置到数组左侧:然后递归,再对切分点左侧和右侧分别排序. 归并排序时递归在前,归并在后,快速排 ...

  6. PCB MVC启动顺序与各层之间数据传递对象关系

    准备着手基于MVC模式写一套Web端流程指示查看,先着手开发WebAPI打通数据接口,后续可扩展手机端 这里将MVC基本关系整理如下: 一.MVC启动顺序 二.MVC各层之间数据传递对象关系

  7. python修改植物僵尸

    import win32process#进程模块 import win32con#系统定义 import win32api#调用系统模块 import ctypes#C语言类型 import win3 ...

  8. Stick ------ 剪枝神题

    这个是自己剪得 , 我感觉已经很不错了  但是不知道哪里出了问题  一直  超时 // 根据所给答案 和 题目要求 最直观的就可以有剪枝的地方 而且 剪枝剪得越早 就越省时省力 // 好的思路也可以省 ...

  9. 【Codeforces】Codeforces Round #374 (Div. 2) -- C. Journey (DP)

    C. Journey time limit per test3 seconds memory limit per test256 megabytes inputstandard input outpu ...

  10. 项目平台统一(前后端IDE、代码风格)

    项目平台统一(前后端IDE.代码风格) 记录人:娄雨禛 前端:Webstorm(HTML+CSS+JavaScript) 后端:IntelliJ IDEA(Java) 代码风格:Java风格代码 代码 ...