BZOJ1833: [ZJOI2010]count 数字计数
1833: [ZJOI2010]count 数字计数
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 1250 Solved: 574
[Submit][Status]
Description
给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。
Input
输入文件中仅包含一行两个整数a、b,含义如上所述。
Output
输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。
Sample Input
1 99
Sample Output
9 20 20 20 20 20 20 20 20 20
HINT
30%的数据中,a<=b<=10^6;
100%的数据中,a<=b<=10^12。
Source
题解:红书上的原题。。。可是答案错了。。。自己又yy了好久
关键语句是这里:
View Code
1 for i:=n downto 1 do 2 begin 3 for j:=0 to 9 do inc(a[j],mi[i-2]*(i-1)*c[i]); 4 for j:=0 to c[i]-1 do inc(a[j],mi[i-1]); 5 inc(a[c[i]],x mod mi[i-1]+1); 6 end; 7 for i:=1 to n do s[i]:='1';val(s,x); 8 dec(a[0],x);
主要步骤是:
1. 0-9的使用次数增加平均使用的次数
2. 0-c[i]-1的使用次数增加作为最高位的使用次数
3. c[i]的使用次数增加 x mod mi[i-1] 其中mi[i]表示10^i
4.循环结束后减去多用的0的个数
代码:
1 var a,b,c,mi:array[-1..15] of int64; 2 s:ansistring; 3 x,y:int64; 4 i:longint; 5 procedure calc(x:int64); 6 var i,j,n:longint; 7 begin 8 fillchar(a,sizeof(a),0); 9 str(x,s);n:=length(s); 10 for i:=1 to n do c[i]:=ord(s[n+1-i])-48; 11 for i:=n downto 1 do 12 begin 13 for j:=0 to 9 do inc(a[j],mi[i-2]*(i-1)*c[i]); 14 for j:=0 to c[i]-1 do inc(a[j],mi[i-1]); 15 inc(a[c[i]],x mod mi[i-1]+1); 16 end; 17 for i:=1 to n do s[i]:='1';val(s,x); 18 dec(a[0],x); 19 end; 20 procedure main; 21 begin 22 mi[0]:=1; 23 for i:=1 to 13 do mi[i]:=mi[i-1]*10; 24 readln(x,y); 25 calc(y); 26 for i:=0 to 9 do b[i]:=a[i]; 27 calc(x-1); 28 write(b[0]-a[0]); 29 for i:=1 to 9 do write(' ',b[i]-a[i]); 30 end; 31 begin 32 assign(input,'input.txt');assign(output,'output.txt'); 33 reset(input);rewrite(output); 34 main; 35 close(input);close(output); 36 end.