SCOI2009windy数

时间:2022-07-31 08:03:47

数位DP,还不怎么会……

其中calc函数的计算分为三部分:

第一部分:统计最高位为0的情况,或者说不足最高位位数的数的个数

第二部分:统计最高位为1到a[len]-1的情况,直接调用数组即可

第三部分:统计与x前(len-i)位相同,但剩下的不同的满足条件的数

这里用到了一个技巧,就是虚开实用,就像虚数的起源那样

f[i,0]如果直接看是没有什么意义的,那个数字开头会为0?

可是这样开了的话,f[i,j]:=f[i,j]+f[i-1,k]j就可以很好的利用

或者我们可以把f[i,j]理解为长度为i的字符串,首字符为j的满足条件的字符串的个数

代码:

 var i,j,k,x,y:longint;
f:array[-..,-..] of longint;
function calc(x:longint):longint;
var i,j,len:longint;
st:string;
a:array[..] of longint;
begin
if x= then exit();
str(x,st);
len:=length(st);
calc:=;
for i:= to len do a[i]:=ord(st[len+-i])-;
for i:= to len- do
for j:= to do
inc(calc,f[i,j]);
for i:= to a[len]- do
inc(calc,f[len,i]);
for i:=len- downto do
begin
for j:= to a[i]- do
if abs(a[i+]-j)>= then inc(calc,f[i,j]);
if abs(a[i+]-a[i])< then break;
end;
end;
procedure main;
begin
for i:= to do f[,i]:=;
for i:= to do
for j:= to do
for k:= to do
if abs(j-k)>= then f[i,j]:=f[i,j]+f[i-,k];
readln(x,y);
writeln(calc(y+)-calc(x));
end;
begin
main;
end.