hdu3886(数位dp)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3886

题意:给一定区间[A,B],一串由/,\,-组成的符号串。求满足符号串的数字个数。

•/表示数字从左到右递增

•\表示数字从左到右递减

•-表示数字从左到右相等

分析:dp[i][j][k],表示当枚举到第i位的数,匹配str[j],前一位是k,满足要求的数字个数.

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int dp[110][110][10];
int dig[110],len;
char str[110],a[110],b[110];
int judge(int i,int pre,int now)
{
    if(str[i]==‘/‘)return pre<now;
    else if(str[i]==‘-‘)return pre==now;
    else if(str[i]==‘\\‘)return pre>now;
}
int  dfs(int pos,int cur,int pre,int limit,int fzore)
{
    if(!pos)return cur==len;
    if(!limit&&~dp[pos][cur][pre])return dp[pos][cur][pre];
    int ed=limit?dig[pos]:9;
    int ans=0;
    for(int i=0;i<=ed;i++)
    {
        if(!fzore)
        {
            if(cur<len&&judge(cur,pre,i))
            ans+=dfs(pos-1,cur+1,i,limit&&i==ed,fzore&&!i);
            //这里为什么能往回走,因为如果pre,i满足str[cur-1],同时
            //已经知道“pre前一位,pre”也满足str[cur-1],这样还是满足要求的数
            //例如数据123455555554321是符合/-\的,5之前都是/,中间都是-,后面都是\。
            else if(cur&&judge(cur-1,pre,i))
            ans+=dfs(pos-1,cur,i,limit&&i==ed,fzore&&!i);
        }
        else ans+=dfs(pos-1,cur,i,limit&&i==ed,fzore&&!i);
        ans%=mod;
    }
    if(!limit)dp[pos][cur][pre]=ans;
    return ans;
}
int solve(char s[],bool left)
{
    int lens=strlen(s),m=0,i=0;
    while(s[i]==‘0‘&&i<lens)i++;
    for(int j=lens-1;j>=i;j--)dig[++m]=s[j]-‘0‘;
    if(left&&m)
    {
        for(int i=1;i<=m;i++)
        {
            if(dig[i])
            {
                dig[i]--;break;
            }
            else dig[i]=9;
        }
    }
    return dfs(m,0,0,1,1);
}
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        len=strlen(str);
        scanf("%s%s",a,b);
        memset(dp,-1,sizeof(dp));
        printf("%08d\n",((solve(b,0)-solve(a,1))+mod)%mod);
    }
}

时间: 2024-11-10 13:29:10

hdu3886(数位dp)的相关文章

数位dp小记

转载自:http://blog.csdn.net/guognib/article/details/25472879 参考: http://www.cnblogs.com/jffifa/archive/2012/08/17/2644847.html kuangbin :http://www.cnblogs.com/kuangbin/category/476047.html http://blog.csdn.net/cmonkey_cfj/article/details/7798809 http:/

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task

hdu 5898 odd-even number 数位DP

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 716    Accepted Submission(s): 385 Problem Description For a number,if the length of continuous odd digits is even and the length

LightOJ1068 Investigation(数位DP)

这题要求区间有多少个模K且各位数之和模K都等于0的数字. 注意到[1,231]这些数最大的各位数之和不会超过90左右,而如果K大于90那么模K的结果肯定不是0,因此K大于90就没有解. 考虑到数据规模,数据组数,这题状态这么表示: dp[i][j][k]:位数为i模K结果为j且各位数之和模K结果为k的数字个数 然后就是转移方程,最后就是统计.. 统计部分好棘手...半乱搞下AC的..还是对数位DP的这一部分太不熟悉了. 1 #include<cstdio> 2 #include<cstr

HDU 4734 F(x)(数位DP)

Description For a decimal number x with n digits (A nA n-1A n-2 ... A 2A 1), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there betwe

hdu 4734 数位dp

http://acm.hdu.edu.cn/showproblem.php?pid=4734 Problem Description For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, plea