poj3150

【题意】

一个n个位置的环,每经过一次置换,每个位置的值会变成上一次周围d范围之内的和,求mod m后置换过k次后每个位置的值

【输入】

第一行n、m、d、k

第二行n个数,表示n个数的初始值

【输出】

输出n个数表示经过k次置换后,每个位置的值


很容易可以看出是矩阵乘法

n<=500

如果构建n*n的矩阵,矩阵乘法复杂度为n^3,那么总体复杂度为n^3log k 是不能接受的

但是可以发现一个矩阵的性质

因为是求d范围之内之和,所以矩阵每一行基本一样,只是错了一位而已

所以求矩阵的时候只需要求一行就够了,复杂度降到n^2,便可以通过了


program poj3150;
type
  arr=array [0..501] of int64;
var
  d,m,n,i,j,k:longint;
  sum:int64;
  h:array [0..501] of int64;
  ans,root:arr;

function convert (now:longint):longint;
begin
  now:=now mod n;
  if now=0 then exit(n)
           else exit(now);
end;

function multiply (a,b:arr):arr;
var
  i,j,k:longint;
  ans:arr;
begin
  fillchar(ans,sizeof(ans),0);
  for i:=1 to n do
    for j:=1 to n do
      ans[i]:=(ans[i]+a[j]*b[convert(i+j-1)]) mod m;
  exit(ans);
end;

procedure quick (now:longint);
begin
  if now=1 then
    begin
      ans:=root;
      exit;
    end;
  quick(now div 2);
  ans:=multiply(ans,ans);
  if now and 1 = 1 then ans:=multiply(ans,root);
end;

begin
  read(n,m,d,k);
  for i:=1 to n do
    read(h[i]);
  for i:=1 to d+1 do
    root[i]:=1;
  for i:=n-d+1 to n do
    root[i]:=1;
  quick(k);
  for i:=1 to n do
    begin
      sum:=0;
      for j:=1 to n do
        sum:=(sum+h[convert(i+j-1)]*ans[j]) mod m;
      write(sum,' ');
    end;
  writeln;
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值