题意:
在范围内满足所给的运算符的数有多少个。
“/” 代表前面的比后面的小 “-”代表前面和后面一样 “\” 代表前面的比后面的大
测试过会出现重复的符号 比如 "///\"
思路:
细心啊细心啊。。!!
数位dp,按位dp
注意几个点就好了:
1、n个运算符至少要有n+1个数。
2、注意开始的状态,第一个数以及第一个运算符。
3、运算符后移注意移动到结束标识就直接返回0。
4、运算符能往后移就往后移。
5、注意大数减一的计算。
6、注意减法的取模。
代码:
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
//2014年9月26日12:49:21
__int64 dp[102][102][12];
int num[102],m=100000000; //因为8位数 所以对100000000取模
char v[102];
int ok(int n,int y,int z)
{
if(n>=101) //特判101
{
if(n==101) n=0;
else return 0;
}
if(v[n]=='\0') return 0; //注意如果字符串结束了 返回0
char x=v[n];
if(x=='/') return y<z;
else if(x=='-') return y==z;
else return y>z;
}
__int64 dfs(int site,int n,int cur,int zero,int f) //位数,运算符,前一个数,前导零,是否是边界
{
if(site==0)
{
if(zero) return 0;
int tep=strlen(v)-1; //是否取到了最后一位
return tep==n;
}
if(!f&&!zero&&~dp[site][n][cur]) return dp[site][n][cur];
int len=f?num[site]:9;
int ans=0;
for(int i=0; i<=len; i++)
{
if(zero)
{
if(i==0) ans+=dfs(site-1,n,cur,zero&&i==0,f&&i==len);
else
{
if(cur==10) ans+=dfs(site-1,101,i,zero&&i==0,f&&i==len); //首先第一位直接放进去 然后因为只有一个数还不能确定运算符
else
{
if(ok(n+1,cur,i)) ans+=dfs(site-1,n+1,i,zero&&i==0,f&&i==len); //这里的原则是运算符能往后走就往后走
else if(ok(n,cur,i)) ans+=dfs(site-1,n==101?0:n,i,zero&&i==0,f&&i==len); //保持原样,然后就是101代表第二个数 因为-1会越界
}
}
}
else
{
if(cur==10) ans+=dfs(site-1,101,i,zero&&i==0,f&&i==len);
else
{
if(ok(n+1,cur,i)) ans+=dfs(site-1,n+1,i,zero&&i==0,f&&i==len);
else if(ok(n,cur,i)) ans+=dfs(site-1,n==101?0:n,i,zero&&i==0,f&&i==len);
}
}
ans%=m;
}
if(!f&&!zero) dp[site][n][cur]=ans;
return ans;
}
__int64 solve(char *x,int f) //f用来区分是否要减一
{
int i=0,cnt=0;
int len=strlen(x);
while(x[i]=='0') i++; //去前导0
if(x[i]=='\0') return 0; //如果是0
for(int j=len-1; j>=i; j--) num[++cnt]=x[j]-'0'; //放入num
if(f) //减一
{
num[1]--;
for(int j=1; j<=cnt; j++)
{
if(num[j]<0)
{
num[j]+=10;
num[j+1]--;
}
}
}
if(num[cnt]==0) cnt--; //注意退位
return dfs(cnt,101,10,1,1);
}
int main()
{
while(scanf("%s",v)!=-1)
{
memset(dp,-1,sizeof(dp));
char x[123],y[123];
scanf("%s%s",x,y); //比较长 要用字符串读入
printf("%08I64d\n",(solve(y,0)-solve(x,1)+m)%m); //减法一定注意取模。。
}
return 0;
}
//2014年9月26日19:08:24