您的位置:首页 > 其它

HDU - 3886 Final Kichiku “Lanlanshu”(数位DP,各种形状模板)

2017-10-12 13:50 357 查看


Final Kichiku “Lanlanshu”

Problem Description

During 2010 summer training, temperlisyer often does problem like this:

“Consider a decimal integer as sequence of digits {D0, D1 … Dn-1} (D0 > 0), if exists such x, y and z, satisfying:

1.Di-1<Di (0<i<=x)

2.Di-1=Di (x<i<=y)

3.Di-1<Di (y<i<=z)

4.Di-1>Di (z<i<=n-1)

We call this integer “Lanlanshu”, now give you two numbers A and B, calculate how many “Lanlanshu” are in [A, B].“

He solved so many of these and finally get bored, and then get crazy! He decided to make up a problem to put this type of problems to an end.

Give you a string str consists only by ‘/’, ‘-‘ and ‘\’, and its length is l. Consider a decimal integer as sequence of digits {D0, D1 … Dn-1} (D0 > 0), define x0=0, xl=n-1, if exists such x1,
x2...xl (x0 < x1 < x2 < ... < xl) satisfying:

1. If str[i]=’/’, Dj-1<Dj (xi<j<=xi+1)

2. If str[i]=’-’, Dj-1=Dj (xi<j<=xi+1)

3. If str[i]=’\’, Dj-1>Dj (xi<j<=xi+1)

We call it Final Kichiku “Lanlanshu”, now give you two numbers A and B, calculate how many Final Kichiku “Lanlanshu” are in [A, B]. This number maybe huge, we only want to now the last 8 digits of the result.

 

Input

Multiple cases (no more than 100), for each case:

The first line is string str, length is below 100.

The second line contains two integers A and B (0≤Ai≤Bi≤10^100).

Input terminates by EOF.

 

Output

For each case, output 8 digits representing the last 8 digits of the number of Final Kichiku “Lanlanshu” in [A, B]. If it’s less than 8 digits, fill it with leading zeros.

 

Sample Input

/\
01221 2012

 

Sample Output

00000315

 

Author

temperlsyer

 

Source

2011 Multi-University Training Contest 5 - Host by BNU

 

题意:给你一个模式串,找到区间内符合该模式的数字的个数。

解题思路:数位DP,好题!以后类似的题直接套这个模板就行了!代码有详细注释,很好理解。

#include<iostream>
#include<deque>
#include<memory.h>
#include<stdio.h>
#include<map>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<bitset>
using namespace std;
typedef long long int ll;
const int MOD=100000000;

int dp[110][110][10];//第i位,前j个字符已经符合,前一个数是k的个数
int dig[200];

string str;//模式串

//去除前导0
string qu(string a){
string ans;
bool have=0;
for(int i=0;i<a.size();i++){
if(!have&&a[i]=='0')
continue;
have=1;
ans.push_back(a[i]);
}
return ans;
}

//字符串减一操作
string subone(string a){
int len=a.size();
if(a[len-1]>'0'){
a[len-1]-=1;
return a;
}
else{
int i=len-1;
while(i>=0&&a[i]<='0')
a[i--]='9';
a[i]-=1;
return a;
}
}

//判断两个字符是否符合当前位的模式串
int ok(int x,int y,char op)
{
if(op=='/')return x<y;
if(op=='-')return x==y;
return x>y;
}

//当前处理到第pos个字符,模式串匹配到了len,前一个数字是last,是否前导0
int dfs(int pos,int len,int last,bool have,bool limit){

if(pos==0)//要判断模式串是否也匹配完
return len==str.size();

//记忆化搜索
if(!limit && !have && dp[pos][len][last]!=-1){
return dp[pos][len][last];
}

int end=limit?dig[pos]:9;
int ans=0;

for(int i=0;i<=end;i++){
if(have){
ans+=dfs(pos-1,0,i,have&&i==0,limit&&i==end);//如果有前导0
}
else{

if(len<str.size()&&ok(last,i,str[len]))
ans+=dfs(pos-1,len+1,i,have&&i==0,limit&&i==end);//贪心的往后匹配,防止////\这种串的干扰
else{
if(len>0&&ok(last,i,str[len-1]))
ans+=dfs(pos-1,len,i,have&&i==0,limit&&i==end);//往后不符合,再看看现在的符不符合
}

}

}
ans%=MOD;

if(!limit&&!have)
dp[pos][len][last]=ans;

return ans;

}

int solve(string x){

int pos=0;

for(pos=0;pos<x.size();pos++)
dig[x.size()-pos]=x[pos]-'0';

return dfs(pos,0,0,1,1);
}

int main(){

while(cin>>str){
memset(dp,-1,sizeof(dp));
string l,r;
cin>>l>>r;
l=qu(l);
r=qu(subone(r));

printf("%08d\n",(solve(r)-solve(l)+MOD)%MOD);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: