CodeVS 1359 数字计数 51nod 1042 数字0-9的数量 Pascal

题目大意:

我的代码又臭又长,但是毕竟是我这个jr想了几天才推出的公式,看别的大神都写数位DP,所以我决定分享一下我的思路。我认为我的思路一向是最好理解的!

要分两种情况讨论:

1.0的情况。我们首先推出0~9中只有1个0,在0~99中有(1+(9*100*1))个0{第一位可以为1~9,第二位可以为0~9,0只可以放在后者,所以乘1},在0~999中有((1+(9*100*1))+(9*101*2))个0~6666为例,先算出0~999中0的个数,在算出1000~5999中0的个数,则为(102*5*3)个0,再从6666中减去6000,继续进行运算。此时我们就可以不用特判第一位数的特殊情况。但是在这里0还有一种特殊情况,就是中间出现一个0,那么我们就要加上0之后的数,例如500233,搜到第二个0时,发现有2个连续的0,就要加上233*2。

2.1~9的情况。与0的推法差不多,就是先算出0~999中1~9的数量,再算出1000~5999中的数量,因为只到5000,所以5以后的不用加上1000,但6要加1。这里有一种情况与0的不相同,就是第一位数要加上这一数字的整十数。例如在0~999中,我们判断完第2~3位数之后,在1~9的情况中都要加上100。

最后加一个特判就完了。程序丑请不要吐槽。

const g:array[0..18] of int64=(1,10,100,1000,10000,100000,1000000,10000000,
                                 100000000,1000000000,10000000000,
                                 100000000000,1000000000000,10000000000000,100000000000000,
                                 1000000000000000,10000000000000000,100000000000000000,100000000000000000);
type arr=array[0..9] of int64;
var n,m,num:int64;
Var i:longint;
var a,b:arr;
var c:string;
var r:arr;
function zero(x:int64;r:boolean):int64;
var ans,w,num,sum:int64;
Var i:longint;
var a:string;
begin
  ans:=0;
  if (x<10)then exit(1);
  str(x,a);w:=length(a);
  if r then
  begin
    num:=1;sum:=9;ans:=1;
    for i:=2 to w-1 do begin inc(ans,num*sum);inc(sum,9);num:=num*10;end;
    inc(ans,(x div g[w-1]-1)*g[w-2]*(w-1));
  num:=0;
  i:=2;while a[i]=‘0‘ do begin  inc(num,x-x div g[w-1]*g[w-1] );inc(i);end;
  inc(ans,num);
    exit(ans+zero(x-x div g[w-1]*g[w-1],false));
  end;
  inc(ans,g[w-2]*(w-1)*(x div g[w-1])+g[w-1]);
  num:=0;
  i:=2;while a[i]=‘0‘ do begin  inc(num,x-x div g[w-1]*g[w-1] );inc(i);end;
  inc(ans,num);
  exit(ans+zero(x-x div g[w-1]*g[w-1],false));
end;
procedure otn(var a:arr;x:int64);
var w,sum,num,ans:int64;
Var i,j:longint;
var a1:string;
begin
  if x<10 then begin for i:=1 to x do inc(a[i]);exit;end;
  str(x,a1);w:=length(a1);ans:=0;
  for i:=1 to 9 do
  begin
    inc(a[i]);
    sum:=9;num:=1;
    for j:=2 to w-1 do
    begin
      inc(a[i],sum*num+g[j-1]);inc(sum,9);num:=num*10;
    end;
    inc(a[i],(x div g[w-1]-1)*g[w-2]*(w-1));
    if (x div g[w-1]>i) then inc(a[i],g[w-1]);
    if (x div g[w-1]=i) then
      begin inc(a[i]);inc(a[i],x-x div g[w-1]*g[w-1]);end;
  end;
  otn(a,x-x div g[w-1]*g[w-1]);
end;
begin
  read(n,m);a[0]:=zero(n,true);b[0]:=zero(m,true);
  otn(a,n);otn(b,m);
  str(n,c);
  for i:=1 to length(c) do begin val(c[i],num);
   if num<>0 then inc(r[num]);end;
   if c[length(c)]=‘0‘ then inc(r[0]);
  str(m,c);
  for i:=2 to length(c)-1 do begin val(c[i],num);
  if num=0 then inc(r[0])end;
  for i:=0 to 9 do inc(b[i],r[i]);
  for i:=0 to 9 do writeln(b[i]-a[i]);
end.

  感谢观看!

时间: 2024-10-12 08:32:59

CodeVS 1359 数字计数 51nod 1042 数字0-9的数量 Pascal的相关文章

51nod 1042 数字0-9的数量 (数位dp、dfs、前导0)

1042 数字0-9的数量 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 取消关注 给出一段区间a-b,统计这个区间内0-9出现的次数. 比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次. Input 两个数a,b(1 <= a <= b <= 10^18) Output 输出共10行,分别是0-9出现的次数 Input示例 10 19 Output示例

51Nod 1042 数字0-9的数量(数位DP)

题意: 求[l,r]中数字0-9分别出现的次数,11算两次1 思路: 数位dp题解好难写,直接贴代码吧 dp[i]表示[0, 10^i-1]中出现j的次数(按i位补全前导0,显然0-9出现的次数是相同的) 最后再减去每一位出现的前导零即可 代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<

(数位DP)51NOD 1042 数字0-9的数量

给出一段区间a-b,统计这个区间内0-9出现的次数. 比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次. 输入 两个数a,b(1 <= a <= b <= 10^18) 输出 输出共10行,分别是0-9出现的次数 输入样例 10 19 输出样例 1 11 1 1 1 1 1 1 1 1 解:被这道题卡了好久...最后自己找了个数模拟了一边流程.举个例子简单说说:对于数5314,我们可以将它拆分为[5310

51nod- 【1042 数字0-9的数量 】

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1042 题目: 1042 数字0-9的数量 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 给出一段区间a-b,统计这个区间内0-9出现的次数. 比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次. Input 两个数a,b(1 <= a <

1833: [ZJOI2010]count 数字计数

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 2951  Solved: 1307[Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

BZOJ_1833_[ZJOI2010]_数字计数_(数位dp)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1833 统计\(a~b\)中数字\(0,1,2,...,9\)分别出现了多少次. 分析 数位dp真是细节又多又容易出错,我都懒得看题解,所以也就懒得写题解了... 注意细节吧还是... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 ll a,b; 6 ll A[10],B[10],n

【BZOJ-1833】count数字计数 数位DP

1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 2494  Solved: 1101[Submit][Status][Discuss] Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a.b,含义如上所述. Output 输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次.

BZOJ 1833 数字计数(统计[a,b]每个数字出现次数)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1833 题意:给定区间[a,b].求区间内0到9每个数字出现的次数. 思路:f[i][j]表示到后i位是否全 0(j=1表示i位之前全0)这个状态某个数字出现的次数,p[i][j]表示这个状态后面有多少个数字.那么当前枚举到的数字为要统计的数字时,答案加 上后面还有多少种数字,即下一个状态的p值.那么我们枚举要统计的数字依次统计即可. i64 f[20][2],p[20][2]; i64

18.n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始, 每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。 当一个数字删除后,从被删除数字的下一个继续删除第m个数字。 求出在这个圆圈中剩下的最后一个数字。

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4263868.html 声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明.谢谢. 题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始, 每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字). 当一个数字