BZOJ 3329 Xorequ:数位dp + 矩阵快速幂
题意
现有如下方程:$ x \oplus 3x = 2x $
其中 $ \oplus $ 表示按位异或。
共 $ T $ 组数据,每组数据给定正整数 $ n $,任务如下:
- 求出小于等于 $ n $ 的正整数中,有多少个数是该方程的解
- 求出小于等于 $ 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[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[1] = 2, g[2] = 3 $
然后用矩阵快速幂加速转移即可:
\]
\]
AC Code
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_L 5
#define MAX_B 70
#define MOD 1000000007
#define int long long
using namespace std;
struct Mat
{
int n,m;
int v[MAX_L][MAX_L];
Mat(int _n,int _m) { n=_n,m=_m,memset(v,0,sizeof(v)); }
Mat() { memset(v,0,sizeof(v)); }
};
int n,t;
int a[MAX_B];
int dp[MAX_B][2];
Mat get_unit(int x)
{
Mat a(x,x);
for(int i=0;i<x;i++) a.v[i][i]=1;
return a;
}
Mat mul(const Mat &a,const Mat &b)
{
Mat c(a.n,b.m);
for(int i=0;i<a.n;i++)
{
for(int j=0;j<b.m;j++)
{
for(int k=0;k<a.m;k++)
{
c.v[i][j]+=a.v[i][k]*b.v[k][j];
c.v[i][j]%=MOD;
}
}
}
return c;
}
Mat pow(Mat a,int k)
{
Mat ans=get_unit(a.n);
while(k>0)
{
if(k&1) ans=mul(ans,a);
a=mul(a,a),k>>=1;
}
return ans;
}
int cal1()
{
int t=n+1,len=0,ans=0;
while(t) a[++len]=(t&1),t>>=1;
a[len+1]=0,dp[0][0]=1;
for(int i=1;i<=len;i++)
{
dp[i][0]=dp[i-1][0]+dp[i-1][1];
dp[i][1]=dp[i-1][0];
}
for(int i=len;i>=1;i--)
{
if(a[i]) ans+=dp[i][0];
if(a[i+1] && a[i]) break;
}
return ans-1;
}
int cal2()
{
Mat a(1,2),b(2,2);
a.v[0][0]=2,a.v[0][1]=3;
b.v[0][1]=b.v[1][0]=b.v[1][1]=1;
return mul(a,pow(b,n-1)).v[0][0];
}
signed main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
printf("%lld\n",cal1());
printf("%lld\n",cal2());
}
}
BZOJ 3329 Xorequ:数位dp + 矩阵快速幂的更多相关文章
- BZOJ 3329: Xorequ [数位DP 矩阵乘法]
3329: Xorequ 题意:\(\le n \le 10^18\)和\(\le 2^n\)中满足\(x\oplus 3x = 2x\)的解的个数,第二问模1e9+7 \(x\oplus 2x = ...
- BZOJ3329 Xorequ(数位dp+矩阵快速幂)
显然当x中没有相邻的1时该式成立,看起来这也是必要的. 于是对于第一问,数位dp即可.第二问写出dp式子后发现就是斐波拉契数列,矩阵快速幂即可. #include<iostream> #i ...
- hdu5564--Clarke and digits(数位dp+矩阵快速幂)
Clarke and digits 问题描述 克拉克是一名人格分裂患者.某一天,克拉克变成了一个研究人员,在研究数字. 他想知道在所有长度在[l,r]之间的能被7整除且相邻数位之和不为k的正整数有多少 ...
- HUST 1569(Burnside定理+容斥+数位dp+矩阵快速幂)
传送门:Gift 题意:由n(n<=1e9)个珍珠构成的项链,珍珠包含幸运数字(有且仅由4或7组成),取区间[L,R]内的数字,相邻的数字不能相同,且旋转得到的相同的数列为一种,为最终能构成多少 ...
- BZOJ 3329 - Xorequ - 数位DP, 矩乘
Solution 发现 $x \ xor \ 2x = 3x$ 仅当 $x$ 的二进制中没有相邻的 $1$ 对于第一个问题就可以进行数位DP 了. 但是对于第二个问题, 我们只能通过递推 打表 来算 ...
- BZOJ 3329 Xorequ (数位DP、矩阵乘法)
手动博客搬家: 本文发表于20181105 23:18:54, 原地址https://blog.csdn.net/suncongbo/article/details/83758728 题目链接 htt ...
- BZOJ3329: Xorequ(二进制数位dp 矩阵快速幂)
题意 题目链接 Sol 挺套路的一道题 首先把式子移一下项 \(x \oplus 2x = 3x\) 有一件显然的事情:\(a \oplus b \leqslant c\) 又因为\(a \oplus ...
- 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 ...
- 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 ...
随机推荐
- HTML Colors
https://www.w3schools.com/html/html_colors.asp <!DOCTYPE html> <html> <body> #169f ...
- Javascript调用WinForm方法
window.external.MyMessageBox('javascript访问C#代码')
- QTimeLine 控制动画(一步一步的往前变化,并在每次变化时都会发出一个frameChanged信号)
QTimeLine顾名思义表示一条时间线,即一个时间序列,该时间序列会按我们实现定义好的间隔一步一步的往前变化,并在每次变化时都会发出一个frameChanged()信号.所以,我们通常会使用该类来驱 ...
- travelsal all files in a dir using recursion shell
#!/bin/bash function getdir(){ ` do dir_or_file=$"/"$element if [ -d $dir_or_file ] then g ...
- elastic search 查询语句
部署了半个月,分析一下数据: 需要提前知道的是,tpot中,每天的数据存一个index,然后每个index里面有不同的type,每条请求一个document 共24万条请求: 查看整个集群所有数据 以 ...
- 五分钟学会 Kotlin 语法
为什么使用Kotlin 项目一期在收尾了终于有时间折腾了,一个多月以来Kotlin从入门到现在,坚持用来开发的切身感受.因为语法与Java的区别挺大的一开始很想放弃,如果不是因为项目在使用,想必很少人 ...
- Linux环境安装nodejs
安装node 去官网下载nodejs 根据下载的文件可以看出它的压缩方式是.xz的方式,所以不能直接使用linux命令tar直接下载. xz -d node-v10.6.0-linux-x64.tar ...
- Differences between Python2 and Python3
@1:str, repr和反引号是Python将值转为字符串的3种方法repr创建一个字符串,它以合法的Python表达式的形式表示该字符串.Python2还有反引号`,但Python3中没有反引号, ...
- jmeter+ant+jenkins接口自动环境搭建
ant 下载地址:http://archive.apache.org/dist/ant/binaries/ 下载:apache-ant-1.9.7-bin.zip 解压到系统盘下:D:\apache- ...
- python16_day11【MQ、Redis、Memcache】
一.RabbitMQ 是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(MQ)是一种应 ...