AtCoder&Luogu[ABC129E] Sum Equals Xor 题解

8 篇文章 0 订阅
7 篇文章 0 订阅
博客内容讲述了如何使用动态规划(DP)解决一类数位DP问题,具体涉及当输入数字串s1时,计算满足特定条件的排列组合数量。通过状态转移方程,博主详细解析了当数位为1或0时的递推关系,并给出了C++实现代码。
摘要由CSDN通过智能技术生成

一看题目,就是一道 dp 题。

我们不妨来确定一个设数:设 d p i , 0 / 1 dp_{i,0/1} dpi,0/1 表示前 i i i 个数与 l l l i i i 个数的关系,那就有两种情况:

  • 如果 j = 0 j=0 j=0 则表示这前 i i i 个数小于 l l l i i i 个数。

  • 如果 j = 1 j=1 j=1 则表示这前 i i i 个数等于 l l l i i i 个数。

那我们就可以得出两种情况:

  • 如果 l i = 1 l_i=1 li=1 ,则:
    • d p i , 0 = d p i − 1 , 0 × 3 + d p i − 1 , 1 dp_{i,0}=dp_{i-1,0} \times 3 + dp_{i-1,1} dpi,0=dpi1,0×3+dpi1,1,解释:前一个的方案既然等于前 l l l i i i 个数,那就有 ( 1 , 0 ) , ( 0 , 1 ) , ( 0 , 0 ) (1,0),(0,1),(0,0) (1,0),(0,1),(0,0),三种情况,以及之前为等于它的前 i i i 位有 ( 0 , 0 ) (0,0) (0,0) 一种方法,因为 ( 1 , 0 ) , ( 0 , 1 ) (1,0),(0,1) (1,0),(0,1) 会使之相等,所以不行。

    • d p i , 1 = d p i − 1 , 1 × 2 dp_{i,1}=dp_{i-1,1} \times 2 dpi,1=dpi1,1×2,解释:只有两种方案,放 ( 1 , 0 ) , ( 0 , 1 ) (1,0),(0,1) (1,0),(0,1)

  • 如果 l i = 0 l_i=0 li=0 ,则:
    • d p i , 0 = d p i − 1 , 0 × 3 dp_{i,0}=dp_{i-1,0}\times 3 dpi,0=dpi1,0×3,解释:三种方案,同上,只不过不能再之前相等的时候填 ( 0 , 0 ) (0,0) (0,0) 会导致这个答案相等,不是 d p i , 0 dp_{i,0} dpi,0
    • d p i , 1 = d p i − 1 , 1 dp_{i,1}=dp_{i-1,1} dpi,1=dpi1,1,解释:之前相等了,只有一种方案 ( 0 , 0 ) (0,0) (0,0),所以只有一个 d p i − 1 , 1 dp_{i-1,1} dpi1,1

代码

#include<iostream>
#define int long long
using namespace std;
int n,dp[105000][2];
string s,s1;
const int mod=1e9+7;
signed main(){
	cin>>s1;
	n=s1.size();
	s=' ',s+=s1;
	dp[0][1]=1;//初始化
	for(int i=1;i<=n;i++){
		dp[i][0]=(dp[i-1][0]*3)%mod;
		if(s[i]=='1'){
			dp[i][0]=(dp[i][0]+dp[i-1][1])%mod;
			dp[i][1]=(dp[i-1][1]*2)%mod;
		}
		else dp[i][1]=dp[i-1][1];
	}
	cout<<(dp[n][0]+dp[n][1])%mod;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值