【BZOJ3329】Xorequ(数位dp+矩阵快速幂)

\(x\oplus3x=2x\) 推出 \(x\oplus2x=3x\),然后又有 \(x+2x=3x\)

定理:若 \(a\oplus b=c\)\(a+b=c\),则不可能存在 \(a\)\(b\) 在二进制下的某一位都是 \(1\)

证明:设 \(a\) 在二进制下的第 \(i\) 位为 \(a_i\)\(b\) 在二进制下的第 \(i\) 位为 \(b_i\)\(c\) 在二进制下的第 \(i\) 位为 \(c_i\)。显然有 \(a_1+b_1=c_1\)\(a_1\oplus b_1=c_1\),因为这一位不可能得到进位。分类讨论一下发现 \(a_1\)\(b_1\) 不可能都是 \(1\),那么第一位就不可能向第二位进位。第二位也就能用同样的方法证出来 \(a_2\)\(b_2\)。以此类推,\(a\)\(b\) 二进制下的任何一位都不能全是 \(1\)

那么我们就可以知道 \(x\)\(2x\) 二进制下的任何一位都不能全是 \(1\)

又因为 \(2x\) 是由 \(x\) 左移一位得到的,所以就等价为:二进制下的 \(x\) 任意相邻的两位都不能是 \(1\)

那么对于第一问,把 \(x\) 转成二进制数,然后数位dp。

对于第二问:

\(f_{i,0/1}\) 代表满足以下条件的二进制数(可以有前导0)的个数:\(i\) 位数,第一位为 \(0/1\) ,没有连续的两位为 \(1\)

那么显然第二问的答案就是 \(f_n=f_{n,0}+f_{n,1}\)

考虑 \(f_i\) 的状态转移:

\(f_{i,0}=f_{i-1,0}+f_{i-1,1}=f_{i-1}\)

\(f_{i,1}=f_{i-1,0}\)

\(f_i=f_{i-1}+f_{i-1,0}=f_{i-1}+f_{i-2}\)

那么这就是一个斐波那契数列,用矩阵快速幂求一下就好了。

代码如下:

#include<bits/stdc++.h>

#define ll long long
#define mod 1000000007

using namespace std;

struct Matrix
{
	ll a[2][2];
	Matrix(){memset(a,0,sizeof(a));}
	void init(){a[0][0]=a[1][1]=1;}
	Matrix operator * (const Matrix &b) 
	{
		Matrix c;
		for(int i=0;i<2;i++)
			for(int j=0;j<2;j++)
				for(int k=0;k<2;k++) 
					c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%mod;
		return c;
	}
}ch;

int t;
int cnt,num[100];
ll n,dp[100][2][2];

void init()
{
	ch.a[1][0]=ch.a[0][1]=ch.a[1][1]=1;
}

ll dfs(int k,bool limit,bool last)
{
	if(!k) return 1;
	if(!dp[k][limit][last])
	{
		dp[k][limit][last]+=dfs(k-1,limit&&!num[k],0);
		if((!last)&&((!limit)||(limit&&num[k]))) dp[k][limit][last]+=dfs(k-1,limit&&num[k],1);
	}
	return dp[k][limit][last];
}

ll solve1()
{
	cnt=0;
	ll x=n;
	while(x)
	{
		num[++cnt]=x&1ll;
		x>>=1ll;
	}
	return dfs(cnt,1,0)-1;
}

ll solve2()
{
	Matrix a=ch,ans;
	ans.init();
	ll b=n+2;
	while(b)
	{
		if(b&1ll) ans=ans*a;
		a=a*a;
		b>>=1ll;
	}
	return ans.a[0][1];
}

int main()
{
	init();
	scanf("%d",&t);
	while(t--)
	{
		memset(dp,0,sizeof(dp));
		scanf("%lld",&n);
		printf("%lld\n",solve1());
		printf("%lld\n",solve2());
	}
	return 0;
}
posted @ 2022-10-28 19:40  ez_lcw  阅读(12)  评论(0)    收藏  举报