解题报告:FZU1692 Key problem 循环矩阵快速幂

来源:互联网 发布:淘宝白色连衣裙 编辑:程序博客网 时间:2024/05/21 17:17
Problem 1692 Key problem

Accept: 196    Submit: 862
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

Whenever rxw meets Coral, he requires her to give him the laboratory key. Coral does not want to give him the key, so Coral ask him one question. if rxw can solve the problem, she will give him the key, otherwise do not give him. rxw turns to you for help now,can you help him?
N children form a circle, numbered 0,1,2, ... ..., n-1,with Clockwise. Initially the ith child has Ai apples. Each round game, the ith child will obtain ( L*A(i+n-1)%n+R*A(i+1)%n ) apples. After m rounds game, Coral would like to know the number of apples each child has. Because the final figure may be very large, so output the number model M.

Input

The first line of input is an integer T representing the number of test cases to follow. Each case consists of two lines of input: the first line contains five integers n,m,L,R and M . the second line contains n integers A0, A1, A2 ... An-1. (0 <= Ai <= 1000,3 <= n <= 100,0 <= L, R <= 1000,1 <= M <= 10 ^ 6,0 <=m < = 10 ^ 9). After m rounds game, output the number model M of apples each child has.

Output

Each case separated by a space. See sample.

Sample Input

1 3 2 3 4 10000 1 2 3

Sample Output

120 133 131

Source

FOJ月赛-2009年3月--- Coral

Submit  Back  Status  Discuss


题意:
给定一个序列,问t次操作后的序列
每次操作:
A[n] = L * A[n-1]  + R * A[n+1] + A[n] 
也就是序列中的前一个数乘以L 加上序列中的后一个数乘以R + 它本身,注意,第一个数的前一个数为最后一个数,最后一个数的后一个数为第一个数。

思路:
很容易写出矩阵,然后发现这是一个循环矩阵(详见 check )那么利用循环矩阵的可积性(循环矩阵乘以循环矩阵得到的新矩阵也是循环矩阵),我们只用正常计算第一行的新矩阵数值,使得加速幂可以由n^3log(t)降到n^2log(t)刚好能满足题目的时间要求。

代码:
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int n,L,R,mod,t;int A[105];int ans[105];void debug(int a[105][105]){    for(int i=0;i<n;i++){        for(int j=0;j<n;j++){            printf("%d%c",a[i][j],j==n-1?'\n':' ');        }    }printf("\n");}void fast_mat(){    int mat[105][105]={0};    int tmp[105]={0};    int res[105][105]={0};    for(int i=0;i<n;i++){        int a = i?i-1:n-1;        int b = i==n-1?0:i+1;        mat[i][i] = res[i][i] = 1;        mat[i][a] = L;        mat[i][b] = R;    }    //debug(mat);    while(t){        if(t&1){            for(int i=0;i<n;i++){tmp[i] = 0;                for(int j=0;j<n;j++){                    tmp[i] = (tmp[i] + res[0][j] * mat[i][j]%mod)%mod;                }            }for(int i=0;i<n;i++){                res[0][i] = tmp[i];            }            for(int i=1;i<n;i++){                for(int j=0;j<n;j++){                    int k = j?j-1:n-1;                    res[i][j] = res[i-1][k];                }            }        }        for(int i=0;i<n;i++){tmp[i] = 0;            for(int j=0;j<n;j++){                tmp[i] = (tmp[i] + mat[0][j] * mat[j][i]%mod)%mod;            }        }for(int i=0;i<n;i++){            mat[0][i] = tmp[i];        }        for(int i=1;i<n;i++){            for(int j=0;j<n;j++){                int k = j?j-1:n-1;                mat[i][j] = mat[i-1][k];            }        }        t >>= 1;        //debug(mat);    }//debug(res);    for(int i=0;i<n;i++){ans[i]=0;        for(int j=0;j<n;j++){            ans[i] = (ans[i] + A[j]*res[i][j]%mod)%mod;        }    }}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%d%d%d%d%d",&n,&t,&L,&R,&mod);        for(int i=0;i<n;i++){            scanf("%d",&A[i]);        }fast_mat();        for(int i=0;i<n;i++){            printf("%d%c",ans[i],i!=n-1?' ':'\n');        }    }return 0;}





0 0
原创粉丝点击