您的位置:首页 > 其它

POJ 3286 How many 0's?(数位DP)

2013-08-09 21:08 363 查看
题目链接

终于过了,边界让我wa了好几次,猥琐的用AC代码对拍,很无奈,用非常麻烦的方法。写一下,估计以后再碰到,肯定看不懂这是写的什么了。

以前做过,统计1和2的,统计0比1和2麻烦多了,有前导0的情况,不太好弄。

算是用统计方法,先把sp[len-1]所有的加上,长度为len-1的情况。

然后就是长度为len的情况。从高位到低位,遍历。

如果此位是0,judge(str+1) + 1 + dfs(str+1),是统计当前为是0的,多少情况,但是会漏解,算是受以前那个题统计1和2的影响把。

如果下一位是0,那么就不用管了,交给下位统计去把。下位不是0,计算会漏掉下位是0的情况,所以定住下位是0,组合一下长度len-2的所有0的个数。

不是0的情况,类似。

以前那个题的题解/article/6803649.html

完全没有策略,乱写,乱搞过的。。。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
#define LL __int64
LL dp[201],sp[201],o[201];
LL judge(char *str)
{
int i,len;
LL ans;
len = strlen(str);
ans = 0;
for(i = 0; i <= len-1; i ++)
{
ans = (ans*10 + str[i]-'0');
}
return ans;
}
LL dfs(char *str)
{
int len;
LL sum;
len = strlen(str);
if(len == 1)
return 1;
sum = (len-1)*o[len-2];
if(str[0] == '0')
{
if(str[1] == '0')
return judge(str+1) + 1 + dfs(str+1);
else if(len >= 3)
return judge(str+1) + 1 +dfs(str+1)+o[len-2] + (len-2)*o[len-3];
else
return judge(str+1) + 1 + dfs(str+1);
}
else
{
if(str[1] == '0')
return (str[0]-'1')*sum + dfs(str+1);
else if(len >= 3)
return (str[0]-'1')*sum + dfs(str+1)+o[len-2] + (len-2)*o[len-3];
else
return (str[0]-'1')*sum + dfs(str+1);
}
}
LL fun(LL x)
{
int i,len;
char str[201];
if(x == 0) return 1;
else if(x < 0) return 0;
len = 0;
while(x)
{
str[len++] = x%10+'0';
x = x/10;
}
for(i = 0; i < len/2; i ++)
{
swap(str[i],str[len-i-1]);
}
str[len] = '\0';
return sp[len-1] + dfs(str);
}
int main()
{
int i;
LL temp = 1,x,y;
dp[1] = 1;
sp[1] = 1;
o[1] = 10;
o[0] = 1;
for(i = 2; i <= 15; i ++)
{
dp[i] = (i-1)*9*temp;
sp[i] = sp[i-1] + dp[i];
o[i] = 10*o[i-1];
temp = temp*10;
}
while ( scanf("%I64d%I64d",&x,&y) && (y>=0) )
{
printf("%I64d\n",fun(y)-fun(x-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: