题意:给你整数a、b,问你[a,b]间每个数字分解成单个数字后,0、1、2、3、4、5、6、7、8、9,分别有多少个

题解:首先找到[0,b]与[0,a-1]进行区间减法,接着就只是求[0,x]

   对于x首先求出他有几位、接着从高位到低位求每个区间

   例如x=15602,则依次求出[1,9],[10,99],[100,999],[1000,9999],这个注意因为没有前导0,所以1-9是一样多的0要少一些

   接着再求[10000,10999],[11000,11999],[12000,12999],[13000,13999],[14000,14999],[15000,15099]..........[15500,15599]

   注意在这儿需求前导0,最后对于个位数的几个进行遍历就好了

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const ll INF=1LL<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=;
int Dig[]= {,,,,,,,,,}; //1-9 10-99 100-999的总个数
int makeup[]= {,,,,,,,,,}; //补全1-9并减去0
int dp1[];//[0,a-1]中0到9的个数
int dp2[];//[0,b]中0到9的个数
void Everyno(int k,int *dp)//计算有k位的dp,例如k=2就是 10-99,不补前导0
{
int num=Dig[k-]*k;
for(int i=; i<; ++i)
{
if(!i)
dp[i]=dp[i]+num-makeup[k-]*;//减去一些0不可能出现的地方
else
dp[i]=dp[i]+num+makeup[k-];
}
}
void Everyyes(int k,int *dp)
{
int num=makeup[k]*k;
for(int i=;i<;++i)
{
dp[i]+=num;
}
}
void Solve(int a,int* dp)//[0,a]中0到9的个数
{
for(int i=; i<; ++i)
dp[i]=;
int enn=;
int dig=;//位数
while(enn<=a)//计算 1-9 10-99 100-999...除开0以外,每位个数都相同且平分差值
{
Everyno(dig,dp);
dig++;
enn=enn*+;
} enn=enn/+;
while(enn<=a)//剩下的数
{
dig=;
while(enn+Dig[dig+]<=a)//例如求1899时 现在为1000,则需要使enn=1099
{
dig++;
enn+=Dig[dig];
}
if(!dig)
break;
Everyyes(dig,dp);
int temp=enn,temp2=dig;
while(temp2--)
temp/=;
while(temp)//补上前面的数,例如求1899在使用1000-1099时需要补上1与0的100个
{
dp[temp%]+=makeup[dig+];
temp/=;
}
enn++;
}
if(enn==)
enn--;
while(enn<=a)//剩下个位几个
{
int temp=enn;
if(temp==)
dp[]++;
while(temp)
{
dp[temp%]++;
temp/=;
}
enn++;
}
return ;
}
int main()
{
int a,b;
while(~scanf("%d %d",&a,&b)&&(a+b))
{
if(a>b)
swap(a,b);
Solve(a-,dp1);
Solve(b,dp2);
for(int i=; i<; ++i)
printf("%d%c",dp2[i]-dp1[i],i==?'\n':' ');
}
return ;
}

  

 其实还有更简单的方法:从后到前枚举每一个位置可能出现没一个值的个数,这儿可以通过打表找到一些规律

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<stdlib.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
const int Inf=0x3f3f3f3f;
const double Pi=acos(-1.0);
const int Max=;
ll Dp(ll n,int m)
{
ll num=,k,l;
if(!m)//0出现的次数是特殊的
{
k=,l=;
while(l<n)
{
num+=((n-k)/(l*)*l);
//printf("%lld %lld %lld\n",num,l,n);
k=k*+;
if((n-k)%(l*)<=(k/)&&(n-k)%(l*)>)
num+=((n-k)%(l*));
l*=;
}
}
else//1-9出现的次数求法一致
{
k=;
l=m;
while(n>=l)//从低到高枚举每一位
{
num+=(n-l)/(k*)*k+min(k,(n-l)%(k*)+);
k*=;
l*=;
}
}
return num;
}
int main()
{
ll n,m;
while(~scanf("%lld %lld",&n,&m)&&(n+m))
{
if(n>m)
swap(n,m);
for(int i=;i<;i++)
{
printf("%lld%c",Dp(m,i)-Dp(n-,i),i==?'\n':' ');//枚举每个数
}
}
return ;
}

UVA 1640 The Counting Problem(按位dp)的更多相关文章

  1. UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。

    /** 题目:UVA 1640 The Counting Problem UVA1640 链接:https://vjudge.net/problem/UVA-1640 题意:求[a,b]或者[b,a] ...

  2. UVA.1640.The Counting Problem / BZOJ.1833.[ZJOI2010]数字计数(数位DP)

    题目链接 \(Description\) 求\([l,r]\)中\(0,1,\cdots,9\)每个数字出现的次数(十进制表示). \(Solution\) 对每位分别DP.注意考虑前导0: 在最后统 ...

  3. UVA - 1640 The Counting Problem (数位dp)

    题意:统计l-r中每种数字出现的次数 很明显的数位dp问题,虽然有更简洁的做法但某人已经习惯了数位dp的风格所以还是选择扬长避短吧(说白了就是菜啊) 从高位向低位走,设状态$(u,lim,ze)$表示 ...

  4. UVa 1640 - The Counting Problem(数论)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  5. UVA 1640 The Counting Problem

    https://vjudge.net/problem/UVA-1640 题意:统计区间[l,r]中0——9的出现次数 数位DP 注意删除前导0 #include<cmath> #inclu ...

  6. UVa 1640 The Counting Problem (数学,区间计数)

    题意:给定两个数m, n,求从 m 到 n 中0-9数字各出现了多少次. 析:看起来挺简单的,其实并不好做,因为有容易想乱了.主要思路应该是这样的,分区间计数,先从个位进行计,一步一步的计算过来.都从 ...

  7. POJ2282 The Counting Problem(数位DP)

    用dp[pos][val][cnt]表示状态,pos是数位,val是当前统计的数字,cnt是目前统计的目标数字的出现次数 注意状态的转移过程,统计数字0时前导0的影响. 1 #include<c ...

  8. 『The Counting Problem 数位dp』

    The Counting Problem Description 求 [L,R]内每个数码出现的次数. Input Format 若干行,一行两个正整数 L 和 R. 最后一行 L=R=0,表示输入结 ...

  9. 【暑假】[深入动态规划]UVa 1380 A Scheduling Problem

     UVa 1380 A Scheduling Problem 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41557 ...

随机推荐

  1. CentOS下搭建LNMP+WordPress+http2.0教程

    此文是本人CentOS下搭建WordPress的一些笔记,环境搭建时间::将看过的几篇文章总结下来,形成一条龙长文.不用大家再找来找去. 本文大概分为此几部分: 一.基础命令更新: 二.服务器加速(非 ...

  2. MySQL主从不一致修复

    场景: 线上正在服务的库由于紧急主从切换导致主从不一致,报错信息如下: Last_Error: Coordinator stopped because there were error(s) in t ...

  3. LinkedList基本用法

    https://blog.csdn.net/i_lovefish/article/details/8042883

  4. Thinkphp的list_to_tree 实现无限级分类列出全部节点

    list_to_tree 使用起来十分方便,具体可查看手冊.由于我在用的时候须要同一时候列出全部节点,所以写了一个递归函数,拿出来供大家參考. public function index(){ Loa ...

  5. [cocos2dx笔记006]流格式日志

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zdhsoft/article/details/36001945 在cocos2dx 2.2.2版本号 ...

  6. java-序列化-001-原生介绍

    一.什么是对象序列化 java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长.但在现实应用中, ...

  7. C/C++中的输出对齐设置

    输出对齐有两个方面,一是输出宽度,一是左对齐还是又对齐. 在C++里面,默认是右对齐,可以通过cout.setf(std::ios::left)调整为左对齐,而且这种调整是全局的 ,一次设置,后面都有 ...

  8. beego——URL构建

    如果可以匹配URl,那么beego也可以生成URL吗?当然可以. UrlFor()函数就是用于构建执行函数的URL的.它把对应控制器和函数名结合的字符串作为第一个参数,其余参数对应URL中的变量.未知 ...

  9. mysql binlog日志的三种模式

    1.statement level模式 每一条会修改数据的sql都会记录到master的bin-log中.slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行.优 ...

  10. java队列的实现

    队列也可以通过数组和链表两种方式来实现. 1.链表方式实现 class Node{ Node next = null; int data; public Node(int data){this.dat ...