您的位置:首页 > 其它

[省选前题目整理][BZOJ 1833][ZJOI 2010]count 数字计数(数位DP)

2015-04-01 16:50 253 查看

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=1833

思路

/article/8152199.html

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 1000

using namespace std;

typedef long long int LL;

LL ans[10]; //ans[i]=数位i在[L,R]中的出现次数
LL pow[13];

void solve(LL x,int sign) //sign为1在答案里加,sign为-1在答案里减
{
if(x==-1) //特判
{
ans[0]++;
return;
}
//求数字1~9的出现次数
for(LL j=1;j<=9;j++)
for(LL i=1;pow[i-1]<=x;i++) //枚举第i位
{
LL len=i-1; //len是该数字右边那部分的长度
LL L=x/pow[i],R=x%pow[i-1]; //L是该数字左边那部分,R是该数字右边那部分
LL t=(x/pow[i-1])%10; //t是x第i位的数位
if(j>t) ans[j]+=L*pow[len]*sign;
else if(j<t) ans[j]+=(L+1)*pow[len]*sign;
else if(j==t) ans[j]+=(L*pow[len]+R+1)*sign;
}
//求0的出现次数
for(LL i=1;pow[i-1]<=x;i++)
{
LL len=i-1; //len是该数字右边那部分的长度
LL L=x/pow[i],R=x%pow[i-1]; //L是该数字左边那部分,R是该数字右边那部分
LL t=(x/pow[i-1])%10; //t是x第i位的数位
if(t>0) ans[0]+=L*pow[len]*sign;
else if(t==0) ans[0]+=((L-1)*pow[len]+R+1)*sign;
}
}

int main()
{
LL a,b;
scanf("%lld%lld",&a,&b);
pow[0]=1;
for(int i=1;i<13;i++) pow[i]=pow[i-1]*10;
solve(b,1);
solve(a-1,-1);
for(int i=0;i<=9;i++) printf("%lld%c",ans[i],i==9?'\n':' ');
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: