Unhappy Hacking II(DP,逆元)

34 篇文章 0 订阅

6458: Unhappy Hacking II

时间限制: 1 Sec   内存限制: 128 MB
提交: 70   解决: 17
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

Sig has built his own keyboard. Designed for ultimate simplicity, this keyboard only has 3 keys on it: the 0 key, the 1 key and the backspace key.
To begin with, he is using a plain text editor with this keyboard. This editor always displays one string (possibly empty). Just after the editor is launched, this string is empty. When each key on the keyboard is pressed, the following changes occur to the string:
The 0 key: a letter 0 will be inserted to the right of the string.
The 1 key: a letter 1 will be inserted to the right of the string.
The backspace key: if the string is empty, nothing happens. Otherwise, the rightmost letter of the string is deleted.
Sig has launched the editor, and pressed these keys N times in total. As a result, the editor displays a string s. Find the number of such ways to press the keys, modulo 109+7.

Constraints
1≤N≤5000
1≤|s|≤N
s consists of the letters 0 and 1.
Partial Score
400 points will be awarded for passing the test set satisfying 1≤N≤300.

输入

The input is given from Standard Input in the following format:
N
s

输出

Print the number of the ways to press the keys N times in total such that the editor displays the string s in the end, modulo 109+7.

样例输入

3

0

样例输出

5

提示

We will denote the backspace key by B. The following 5 ways to press the keys will cause the editor to display the string 0 in the end: 00B, 01B, 0B0, 1B0, BB0. In the last way, nothing will happen when the backspace key is pressed.

来源

ABC043&ARC059 

题意:给出数字n和一个字符串,共n次操作,每次可进行在字符串最后加0,加1,删除一个字符,问构建出下面给的字符串一共多少种方法。

题解:DP,dp[i][j]进行i次操作得到长度为j的字符串的方案数,转移方程经观察得,当进行添加时dp[i+1][j+1]=dp[i][j]*2+dp[i+1][j+1];当进行删除的时候:dp[i+1][j-1]=dp[i][j]+dp[i+1][j-1];需要注意j-1时是否越界,max(0,j-1)。最后因为将每个字符看成1或0的方案数,还需要除以qpow(2,len),逆元一下即可。

#include<bits/stdc++.h>
#define max(a,b) (a)>(b)?(a):(b)
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll qpow(ll a,int b){
    ll ans=1;
    while(b){
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }return ans;
}
int dp[5050][5050]={0};
int n,len;
char s[5050];
int main()
{

    scanf("%d%s",&n,s);
    len=(int)strlen(s);
    dp[0][0]=1;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=i;j++){
            dp[i+1][j+1]=(int)(( 2ll*dp[i][j]%mod + dp[i+1][j+1] )%mod);
            dp[i+1][max(j-1,0)]=(int)(( 0ll+dp[i][j]+dp[i+1][max(j-1,0)])%mod);
        }
    }
    int ans=(int)(qpow(qpow(2,len),mod-2)*dp[n][len]%mod);
    printf("%d\n",ans);
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值