算法:DP
一开始这道题看得我蒙蒙的,看了半天想到了递推,无奈状态表示对了但是方程写错了。后来看了题解才发现并不是很难,一言蔽之,还是爱的不够啊~
总的来说思路还算是有的,设f[i,j]表示2^k进制数长度为i位,最高位是j的方案数,则很容易的得出f[i,j]=f[i-1,j+1]+f[i-1,j+2]+...+f[i-1,2^k-1],通过观察f[i-1,j+2]+...+f[i-1,2^k-1]不难看出,这实际上就是f[i,j+1],因此我们不必累加前面的所有那么多项的式子,原式可以化简为f[i,j]=f[i-1,j+1]+f[i,j+1]。
按照以上的那个式子,我们就可以倒序的求解了。
另外要特殊注意的是,最高位,即长度为m mod n,它的取值范围只存在与1~2^(n mod m)-1之中,而不同于其它位的长度为1~2^k-1,但是如此以来,我们会漏掉2^(m mod n)~2^k-1这些状态,而由上面的推导可知,前面的状态是由后面的状态推出来的,因此我们要过滤一下状态,对于求最高位,只有在j<=2^(m mod n)-1时才进行累加。
一开始这道题看得我蒙蒙的,看了半天想到了递推,无奈状态表示对了但是方程写错了。后来看了题解才发现并不是很难,一言蔽之,还是爱的不够啊~
总的来说思路还算是有的,设f[i,j]表示2^k进制数长度为i位,最高位是j的方案数,则很容易的得出f[i,j]=f[i-1,j+1]+f[i-1,j+2]+...+f[i-1,2^k-1],通过观察f[i-1,j+2]+...+f[i-1,2^k-1]不难看出,这实际上就是f[i,j+1],因此我们不必累加前面的所有那么多项的式子,原式可以化简为f[i,j]=f[i-1,j+1]+f[i,j+1]。
按照以上的那个式子,我们就可以倒序的求解了。
另外要特殊注意的是,最高位,即长度为m mod n,它的取值范围只存在与1~2^(n mod m)-1之中,而不同于其它位的长度为1~2^k-1,但是如此以来,我们会漏掉2^(m mod n)~2^k-1这些状态,而由上面的推导可知,前面的状态是由后面的状态推出来的,因此我们要过滤一下状态,对于求最高位,只有在j<=2^(m mod n)-1时才进行累加。
在优化方面,考虑用8位高精度使用的内存较高,因此采用滚动数组进行优化。
program digital;
const
maxn=512;
cifang:array [0..10] of longint=(1,2,4,8,16,32,64,128,256,512,1024);
type
arr=array [0..50] of int64;
var
maxlen,n,m:longint;
f:array [0..1,0..maxn] of arr;
ans:arr;
procedure init;
var
i:longint;
begin
readln(n,m);
maxlen:=m div n;
for i:=cifang[n]-1 downto 1 do
begin
f[0,i,0]:=1;
f[0,i,1]:=1;
end;
ans[0]:=1;
ans[1]:=0;
end;
function HPP(x,y:arr):arr;
var
i,len,t:longint;
begin
t:=0;
fillchar(HPP,sizeof(HPP),0);
if x[0]>=y[0] then len:=x[0] else len:=y[0];
HPP[0]:=len;
for i:=1 to len do
begin
HPP[i]:=x[i]+y[i]+t;
t:=HPP[i] div 1000000000;
HPP[i]:=HPP[i] mod 1000000000;
end;
if t>0 then
begin
inc(HPP[0]);
HPP[HPP[0]]:=t;
end;
while (HPP[HPP[0]]=0) and (HPP[0]>1) do dec(HPP[0]);
end;
procedure main;
var
i,j,t:longint;
begin
{先处理不是最高位的位置。}
for i:=1 to maxlen-1 do
begin
t:=i mod 2;
for j:=cifang[n]-1 downto 1 do
begin
f[t,j]:=HPP(f[1-t,j+1],f[t,j+1]);
ans:=HPP(ans,f[t,j]);
end;
end;
t:=maxlen mod 2;
{处理最高位+特殊限制。}
if m mod n>0 then
begin
for j:=cifang[n]-1 downto 1 do
begin
f[t,j]:=HPP(f[1-t,j+1],f[t,j+1]);
if j<=cifang[m mod n]-1 then ans:=HPP(ans,f[t,j]);
end;
end;
end;
procedure print(x:arr);
var
i:longint;
begin
write(x[x[0]]);
for i:=x[0]-1 downto 1 do
begin
if x[i]<100000000 then write(0);
if x[i]<10000000 then write(0);
if x[i]<1000000 then write(0);
if x[i]<100000 then write(0);
if x[i]<10000 then write(0);
if x[i]<1000 then write(0);
if x[i]<100 then write(0);
if x[i]<10 then write(0);
write(x[i]);
end;
writeln;
end;
begin
assign(input,'digital.in'); reset(input);
assign(output,'digital.out'); rewrite(output);
init;
main;
print(ans);
close(input); close(output);
end.