一看题目,就是一道 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=dpi−1,0×3+dpi−1,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=dpi−1,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=dpi−1,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=dpi−1,1,解释:之前相等了,只有一种方案 ( 0 , 0 ) (0,0) (0,0),所以只有一个 d p i − 1 , 1 dp_{i-1,1} dpi−1,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;
}