计数【NOIP2016提高A组模拟7.15】

题目

这里写图片描述
样例输入:
这里写图片描述
2 10
样例输出:
这里写图片描述
90

数据范围:
这里写图片描述


剖解题目:题目说的很明了了。


思路:求方案数,一般会设计道dp,规律之类的。


解法:数位DP,设f[i][j]表示当前到了第i位,这一位的数字是j的方案数。
自然有:f[i][j]=f[i-1][l]+f[i][j]。(0<=l < k)且(l<>0 and j<>0).
看到这位数,很明显的高精度了。
然而单纯的高精加速度会较慢,我们惊讶发现其实只有f[i][0]与f[i][!0]是不同的,所以我们可以将所有的f[i][!0]都加在一起,也就是弄一个高精乘。
然而,高精度实在是难搞,调了半天终于调对了,真是蛋疼!(ノಠ益ಠ)ノ彡┻━┻


代码:

type
        arr=array[0..1,0..1,0..2000]of longint;
const mo=100000000;
var
        f:arr;
        ans:array[0..1000]of longint;
        n,k,i,j,x,y,z,p,q:longint;
procedure
        add(x,y,xx,yy:longint);
var
        i,t:longint;
begin
        if f[x,xx,0]>f[y,yy,0] then i:=f[x,xx,0]
        else i:=f[y,yy,0];
        t:=0;
        for i:=1 to i do
        begin
                if i>f[x,xx,0] then f[x,xx,i]:=0;
                if i>f[y,yy,0] then f[y,yy,i]:=0;
                f[x,xx,i]:=f[x,xx,i]+f[y,yy,i]+t;
                t:=f[x,xx,i] div mo;
                f[x,xx,i]:=f[x,xx,i] mod mo;
        end;
        if t>0 then
        begin
                inc(i);
                f[x,xx,i]:=t;
        end;
        f[x,xx,0]:=i;
end;
procedure
        quick(x,o,k:longint);
var
        i,t:longint;
begin
        i:=f[x,o,0];
        t:=0;
        for i:=1 to i do
        begin
                f[x,o,i]:=f[x,o,i]*k+t;
                t:=f[x,o,i] div mo;
                f[x,o,i]:=f[x,o,i] mod mo;
        end;
        while t<>0 do
        begin
                inc(i);
                f[x,o,i]:=f[x,o,i]+t;
                t:=f[x,o,i] div mo;
        end;
        f[x,o,0]:=i;
end;
procedure
        printf(x:longint);
var
        i:longint;
        s:string;
begin
        write(f[x,1,f[x,1,0]]);
        for i:=f[x,1,0]-1 downto 1 do
        begin
                f[x,1,i]:=f[x,1,i]+mo;
                str(f[x,1,i],s);
                delete(s,1,1);
                write(s);
        end;
end;
begin
        readln(n,k);
        if k=1 then writeln(0)
        else if n=1 then writeln(k-1)
        else begin
                f[0,0,0]:=1;
                f[0,0,1]:=1;
                f[0,1,0]:=1;
                f[0,1,1]:=1;
                p:=1; q:=0;
                for i:=2 to n do
                begin
                        quick(q,1,k-1);
                        f[p,0]:=f[q,1];
                        f[p,1]:=f[q,1];
                        add(p,q,1,0);
                        q:=p;
                        p:=p xor 1;
                end;
                quick(q,1,k-1);
                printf(q);

        end;
end.

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值