题意:
在范围内满足所给的运算符的数有多少个。
“/” 代表前面的比后面的小 “-”代表前面和后面一样 “\” 代表前面的比后面的大
测试过会出现重复的符号 比如 "///\"
思路:
细心啊细心啊。。!!
数位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
时间: 2024-10-22 02:35:02