Hnoi 第一题 homework 题解

来源:互联网 发布:python正则表达式题目 编辑:程序博客网 时间:2024/05/16 06:26

【题目大意】

求123456789101112131415……n构成的数mod m的值。

【基本思路】

我一开始用的是模拟,用一个字符串保存数字,再取模。这样显然超时,只能过一两个点。

后来才知道是用动态规划写的,方程是P(i)=P(i-1)*10^k+ i .

当然,直接动态规划的话效果也不好,所以我们用矩阵加速动归。

【矩阵构造】

我一开始是用别人的矩阵,也不知道原理。后来自己用草稿纸算,找到一个规律,并发现以前的矩阵有问题,所以才做错了的,于是我修改矩阵之后就AC了。

【具体做法】

设3*3矩阵Bas[i]={{10^k,0,0},{1,1,0},{1,1,1}}

答案矩阵Ans=Bas[1]^9 * bas[2]^90 * bas[3]^900 *…*bas[k]^t  (10k<=t<10k+1);

Answer=Ans[3][1]

由于矩阵有二分幂算法和乘法结合率,我们可以先二分出bas[i]^k再做几次矩阵乘法就可以了。

【我的程序】

type

  mat=array[1..3,1..3]of qword;

var

  n,m:qword; i,j:longint;

  base,ans,c:mat; dk,dt,dp:qword;

 

function mul(a,b:mat):mat;  //矩阵乘法

var i,j,k:longint; sum:qword; c:mat;

begin

  for i:=1 to 3 do for j:=1 to 3 do mul[i,j]:=0;

  for i:=1 to 3 do

    for j:=1 to 3 do

      for k:=1 to 3 do

        mul[i,j]:=(mul[i,j]+a[i,k]*b[k,j] mod m) mod m;

end;

Function muls(var b:mat;t:qword):mat;  //二分快速幂

var d:mat;

begin

  if t=1 then exit(b);

  muls:=muls(b,t div 2);

  muls:=mul(muls,muls);

  if odd(t) then exit(mul(muls,b)) else exit(muls);

end;

 

begin

 assign(input,'input.txt'); assign(output,'output.txt');

 reset(input); rewrite(output);

  readln(n,m);

 

  base[2][1]:=1; base[2][2]:=1; base[3][2]:=1; base[3][3]:=1;

  base[1][1]:=1; base[3][1]:=1;        //构造基本矩阵

 

  ans[1,1]:=1; ans[2,2]:=1; ans[3,3]:=1;

  dk:=1; dt:=9; dp:=0;

  while true do

    begin

      dk:= dk*10;

      c:=base; c[1,1]:=dk mod m; //修改基本矩阵

      if n<dk then

        begin

          c:=muls(c,n-dp);

          ans:=mul(ans,c);

          break;

        end

        else

        begin

          c:=muls(c,dt);

          ans:=mul(ans,c);

          dp:=dk-1;

          dt:=dt*10;

        end;

    end;

  writeln(ans[3,1]);

  close(input); close(output);

end.

原创粉丝点击