传送门

题意

现有如下方程:$ x \oplus 3x = 2x $

其中 $ \oplus $ 表示按位异或。

共 $ T $ 组数据,每组数据给定正整数 $ n $,任务如下:

  1. 求出小于等于 $ n $ 的正整数中,有多少个数是该方程的解
  2. 求出小于等于 $ 2^n $ 的正整数中,有多少个数是该方程的解,输出 $ mod $ $ 10^9+7 $ 的值。

$ (n \leq 10^{18}, T \leq 1000) $

题解

第一问

方程 $ x \oplus 3x = 2x $ 等价于 $ x \oplus 2x = 3x $ 。

由于 $ x + 2x = 3x $ ,并且“按位异或”相当于“不进位加法“

所以我们可以知道,一个数 $ x $ 是该方程的解的充要条件为:$ x $ 在二进制表示下,没有两个相邻的 $ 1 $ 。

$ f[i][0/1] $ 表示所有二进制下长度为 $ i $,且最右边一位为 $ 0/1 $ 的数中,满足没有两个相邻的 $ 1 $ 的数的个数。

所以有:

\[f[i][0] = f[i-1][0] + f[i-1][1]
\]

\[f[i][1] = f[i-1][0]
\]

边界条件为:$ f[0][0] = 1 $

然后按位统计,算出小于等于 $ n $ 的答案:

  • 先让 $ n = n + 1 $ (因为最后算出的是小于某个数的答案,而这里要求小于等于)
  • 从高到低枚举 $ n $ 的每一个二进制位 $ a[i] $
  • 如果 $ a[i] = 1 $ ,那么 $ ans = ans + f[i][0] $ 。(此时累加的是第 $ i-1 $ 及之前位和原数匹配时的答案)
  • 如果 $ a[i] = 1 $ 且 $ a[i+1] = 1 $ ,退出循环。因为此时的前缀已经有两个 $ 1 $ 相邻,之后的答案都是不合法的。

注意最终答案为 $ ans - 1 $ ,因为不包含 $ 0 $ 这个答案。

复杂度 $ O(logn) $

第二问

$ g[i] $ 表示二进制下长度为 $ i $ ,满足没有两个相邻的 $ 1 $ 的数的个数。

由于题目要求区间 $ [1, 2^i] $ 的答案,$ g[i] $ 表示区间 $ [0, 2^i-1] $ 的答案

而 $ 0 $ 和 $ 2^i $ 一定都满足条件,所以相互抵消掉了。

所以题目所求 $ ans = g[n] $

然后考虑如何求 $ g[i] $ (分两种情况):

  • $ g[i] $ 中以 $ 0 $ 结尾的所有数,相当于在 $ g[i-1] $ 中的所有数末尾添了一个 $ 0 $
  • $ g[i] $ 中以 $ 1 $ 结尾的所有数,相当于在 $ g[i-2] $ 中的所有数末尾添了一个 $ 01 $

所以有:

\[g[i] = g[i-1] + g[i-2]
\]

边界条件为:$ g[1] = 2, g[2] = 3 $

然后用矩阵快速幂加速转移即可:

\[\begin{bmatrix} g[i] & g[i+1] \end{bmatrix} \times \begin{bmatrix} 0 & 1 \\ 1 & 1 \end{bmatrix} = \begin{bmatrix} g[i+1] & g[i+2] \end{bmatrix}
\]

\[\begin{bmatrix} g[1] & g[2] \end{bmatrix} \times \begin{bmatrix} 0 & 1 \\ 1 & 1 \end{bmatrix}^{n-1} = \begin{bmatrix} g[n] & g[n+1] \end{bmatrix}
\]

AC Code

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #define MAX_L 5
  5. #define MAX_B 70
  6. #define MOD 1000000007
  7. #define int long long
  8. using namespace std;
  9. struct Mat
  10. {
  11. int n,m;
  12. int v[MAX_L][MAX_L];
  13. Mat(int _n,int _m) { n=_n,m=_m,memset(v,0,sizeof(v)); }
  14. Mat() { memset(v,0,sizeof(v)); }
  15. };
  16. int n,t;
  17. int a[MAX_B];
  18. int dp[MAX_B][2];
  19. Mat get_unit(int x)
  20. {
  21. Mat a(x,x);
  22. for(int i=0;i<x;i++) a.v[i][i]=1;
  23. return a;
  24. }
  25. Mat mul(const Mat &a,const Mat &b)
  26. {
  27. Mat c(a.n,b.m);
  28. for(int i=0;i<a.n;i++)
  29. {
  30. for(int j=0;j<b.m;j++)
  31. {
  32. for(int k=0;k<a.m;k++)
  33. {
  34. c.v[i][j]+=a.v[i][k]*b.v[k][j];
  35. c.v[i][j]%=MOD;
  36. }
  37. }
  38. }
  39. return c;
  40. }
  41. Mat pow(Mat a,int k)
  42. {
  43. Mat ans=get_unit(a.n);
  44. while(k>0)
  45. {
  46. if(k&1) ans=mul(ans,a);
  47. a=mul(a,a),k>>=1;
  48. }
  49. return ans;
  50. }
  51. int cal1()
  52. {
  53. int t=n+1,len=0,ans=0;
  54. while(t) a[++len]=(t&1),t>>=1;
  55. a[len+1]=0,dp[0][0]=1;
  56. for(int i=1;i<=len;i++)
  57. {
  58. dp[i][0]=dp[i-1][0]+dp[i-1][1];
  59. dp[i][1]=dp[i-1][0];
  60. }
  61. for(int i=len;i>=1;i--)
  62. {
  63. if(a[i]) ans+=dp[i][0];
  64. if(a[i+1] && a[i]) break;
  65. }
  66. return ans-1;
  67. }
  68. int cal2()
  69. {
  70. Mat a(1,2),b(2,2);
  71. a.v[0][0]=2,a.v[0][1]=3;
  72. b.v[0][1]=b.v[1][0]=b.v[1][1]=1;
  73. return mul(a,pow(b,n-1)).v[0][0];
  74. }
  75. signed main()
  76. {
  77. scanf("%lld",&t);
  78. while(t--)
  79. {
  80. scanf("%lld",&n);
  81. printf("%lld\n",cal1());
  82. printf("%lld\n",cal2());
  83. }
  84. }

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. BZOJ3329 Xorequ(数位dp+矩阵快速幂)

    显然当x中没有相邻的1时该式成立,看起来这也是必要的. 于是对于第一问,数位dp即可.第二问写出dp式子后发现就是斐波拉契数列,矩阵快速幂即可. #include<iostream> #i ...

  3. hdu5564--Clarke and digits(数位dp+矩阵快速幂)

    Clarke and digits 问题描述 克拉克是一名人格分裂患者.某一天,克拉克变成了一个研究人员,在研究数字. 他想知道在所有长度在[l,r]之间的能被7整除且相邻数位之和不为k的正整数有多少 ...

  4. HUST 1569(Burnside定理+容斥+数位dp+矩阵快速幂)

    传送门:Gift 题意:由n(n<=1e9)个珍珠构成的项链,珍珠包含幸运数字(有且仅由4或7组成),取区间[L,R]内的数字,相邻的数字不能相同,且旋转得到的相同的数列为一种,为最终能构成多少 ...

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

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

  6. BZOJ 3329 Xorequ (数位DP、矩阵乘法)

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

  7. BZOJ3329: Xorequ(二进制数位dp 矩阵快速幂)

    题意 题目链接 Sol 挺套路的一道题 首先把式子移一下项 \(x \oplus 2x = 3x\) 有一件显然的事情:\(a \oplus b \leqslant c\) 又因为\(a \oplus ...

  8. 2018.09.27 hdu5564Clarke and digits(数位dp+矩阵快速幂)

    传送门 好题啊. 我只会写l,rl,rl,r都很小的情况(然而题上并没有这种数据范围). 但这个dp转移式子可以借鉴. 我们用f[i][j][k]f[i][j][k]f[i][j][k]表示当前在第i ...

  9. 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 ...

随机推荐

  1. JDK源码分析之concurrent包(三) -- Future方式的实现

    上一篇我们基于JDK的源码对线程池ThreadPoolExecutor的实现做了分析,本篇来对Executor框架中另一种典型用法Future方式做源码解读.我们知道Future方式实现了带有返回值的 ...

  2. Eclipse Spring Tool Suite插件安装

    目录 Eclipse Spring Tool Suite插件安装 Eclipse Spring Tool Suite插件安装 1.登录网址:http://spring.io/tools/sts/all ...

  3. php 图片验证码

    1.原理 数组中每个图片对应一个值->随机值->获取并保存到$_SESSION中,->获取随机值对应的图片,->通过__FILE__输出图片,->浏览器验证 2.代码 c ...

  4. info 手册

      info flex 可以查看flex帮助. h就可以看到相关命令,常用命令已经加粗: x           关闭此帮助窗口. q           一并退出 Info. RET         ...

  5. 2015-03-22——js常用其它方法

    Function Function.prototype.method = function (name, func) {    this.prototype[name] = func;  //此时th ...

  6. Python WSGI v1.0 中文版(转)

    add by zhj: WSGI全称Web Server Gateway Interface,即Web网关接口.其实它并不是OSI七层协议中的协议,它就是一个接口而已,即函数,而WSGI规定了该接口的 ...

  7. Codeforce 475 C. Kamal-ol-molk&#39;s Painting

    从最左上的点開始枚举长宽.... C. Kamal-ol-molk's Painting time limit per test 2 seconds memory limit per test 256 ...

  8. java正则匹配

    java正则提取需要用到Matcher类,下面给出案例示例供参考 需要提取车牌号中最后一个数字,比如说:苏A7865提取5,苏A876X提取6import java.util.regex.Matche ...

  9. 你真的会用Retrofit2吗?Retrofit2完全教程

    本文注目录: Retrofit入门 Retrofit注解详解 Gson与Converter RxJava与CallAdapter 自定义Converter 自定义CallAdapter 其它说明 前言 ...

  10. MFC实现简单飞机大战(含游戏声音)

    1 实验内容 本实验主要是实现简单的飞机大战游戏,包含游戏声音.碰撞后爆炸效果,有大小敌机等.所用到的知识点如下: 1.贴图技术 2.飞机类.子弹类实现 3.位图移动 4.碰撞判断,实现爆炸效果 5. ...