sicily 1370 How many 0's? 递推 规律

//找规律 算m到n有数字中有几个0,包括m n
//先设数组 dp[i]表示 i长度,第一个固定且非0的所有数字的0的个数
//基于dp从,dp和可以直接算 0到1000000 ,不包括100000
//剩下的数字由高位向低位算,分0和非0去暴力就可以了
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

long long m, n;
long long result;
long long dp[17];

long long act[17];
long long f( long long k )
{
	long long k2 = k;
	if( k == -1 ) return 0;
	long long result = 0;
	long long temp[34], m = 0;
	while( k )
	{
		temp[m++] = k % 10;
		k /= 10;
	}
	result += 1;
	for( int i = 2;i <= m-1;i++ )
		result += 9*dp[i];
	result += (temp[m-1]-1) * dp[m];
	for( int i = m-2;i >= 0;i-- )
	{
		if( temp[i] > 0 ) result += ( act[i] + (temp[i])*dp[i+1] );
		else              result += k2 % act[i]+1 ;

	}
	return result;
}
int main()
{
	act[0] = 1;
	for( int i = 1;i <= 16;i++ ) act[i] = act[i-1]*10;
	dp[1] = 0; dp[2] = 1;
	for( int l = 3;l <= 16;l++ )
	{
		dp[l] = dp[l-1]*10 + act[l-2];
	}
	while( scanf("%lld%lld",&m,&n ) && m >= 0 )
	{
		//f(n);
		printf( "%lld\n",f(n)-f(m-1) );
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值