【BZOJ3329】Xorequ(数位DP)

博客探讨了BZOJ3329题目的解决方案,主要涉及数位动态规划(DP)的方法。对于输入的大整数N,题目要求找到满足x异或2x等于3x的数。作者指出,当x的二进制表示中相邻两位不全为0时,条件成立。文章提供了样例输入和输出,并提示在处理第一问时直接使用数位DP,而第二问可以通过矩阵快速幂来求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Input
第一行一个正整数,表示数据组数据 ,接下来T行

每行一个正整数N

Output

2*T行

第2*i-1行表示第i个数据中问题一的解,

第2*i行表示第i个数据中问题二的解,

Sample Input

1
1

Sample Output

1
2

HINT

x=1与x=2都是原方程的根,注意第一个问题的解不要mod 109+7

0≤N≤10^18

1≤T≤1000

我们先分析一下题目条件, x 异 或 3 x = = 2 x x异或3x==2x x3x==2x这个条件等同于 x 异 或 2 x = = 3 x x异或2x==3x x2x==3x,因为 2 x = = 1 < < x 2x==1<<x 2x==1<<x,所以题目要求的这个数就是二进制下相邻两位不都为零。

N这么大,首推数位DP

第一问直接数位DP就行。

第二问用矩阵快速幂算就行了

#include<bits/stdc++.h>
#define mod 1000000007
#define int long long
using namespace std;
struct data
{
	int a[2][2];
}a,b,none,none1;
int f[110],t,n,cnt,c[101],ans;
data operator *(data a,data b)
{
	data ans=none1;
	for(int i=0;i<=1;i++)
	{
		for(int j=0;j<=1;j++)
		{
			for(int k=0;k<=1;k++)
			{
				ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
			}
		}
	}
	return ans;
}
data fastpow(data a,int n)
{
	data ans=none;
	while(n)
	{
		if(n&1)
		{
			ans=ans*a;
		}
		a=a*a;
		n>>=1;
	}
	return ans;
}
signed main()
{
	f[0]=0;
	f[1]=1;
	for(int i=2;i<=70;i++)
	{
		f[i]=f[i-1]+f[i-2];
	}
	none.a[0][0]=none.a[1][1]=1;
	a.a[0][0]=a.a[0][1]=a.a[1][0]=1;
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld",&n);
		n++;
		b=fastpow(a,n);//第二问
		ans=0;
		cnt=0;
		while(n)//第一问
		{
			c[++cnt]=n%2;
			n/=2;
		}
		c[cnt+1]=0;
		for(int i=cnt;i;i--)
		{
			if(c[i])
			{
				ans+=f[i+1];
			}
			if(c[i]&&c[i+1])
			{
				break;
			}
		}
		printf("%lld\n%lld\n",ans-1,b.a[0][0]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值