首页 > 代码库 > 快速矩阵幂

快速矩阵幂

问题描述

    今天Jack送个rose一个神奇的礼物“魔力手环”。      

    魔力手环上面有n个数字(构成一个环),当这个魔力手环每次使用魔力的时候就会发生一种奇特的变化:每个数字会变成自己跟后面一个数字的和(最后一个数字的后面一个数字是第一个),一旦某个位置的数字大于等于100就马上对100取模(比如某个位置变为103,就会自动变为3).现在给出这个魔力手环的构成,请你计算出使用k次魔力之后魔力手环的状态。

输入描述

输入数据包括两行:

第一行为两个整数n(2 ≤ n ≤ 200)和k(1 ≤ k ≤ 2000000000),以空格分隔

第二行为魔力手环初始的n个数,以空格分隔。范围都在0至99.

 

输出描述

输出魔力手环使用k次之后的状态,以空格分隔,行末无空格。

样例输入
3 2
1 2 3
样例输出
8 9 7
来源
第十二届中北大学程序设计竞赛
#include"stdio.h"
#include"cstdio"
#include"algorithm"
#include"string.h"
typedef long long ll;
using namespace std;
const int max_n=210;
int n;
struct mat
{
    int m[max_n][max_n];
};
mat multi(mat X,mat Y)
{
    mat Z;
    memset(Z.m,0,sizeof(Z.m));
    int i,j,k;
    for(i=0;i<=0;i++)
    {
        for(j=0;j<n;j++)
        {
            for(k=0;k<n;k++)
            Z.m[i][j]+=(X.m[i][k]*Y.m[k][j]%100);
        }
        Z.m[i][j]=Z.m[i][j]%100;
    }
    for(i=1;i<n;i++)
    {
        for(j=1;j<n;j++)
        Z.m[i][j]=Z.m[i-1][j-1];
        Z.m[i][0]=Z.m[i-1][n-1];
    }
    return Z;
}
mat magic(ll k)
{
    mat B;
    int i,j;
    for(i=0;i<n-1;i++)
    B.m[i][i]=B.m[i+1][i]=1;
    B.m[0][n-1]=B.m[n-1][n-1]=1;
    mat C;
    memset(C.m,0,sizeof(C.m));
    for(i=0;i<n;i++)
    C.m[i][i]=1;
    while(k>0)
    {
        if(k&1) C=multi(C,B);
        B=multi(B,B);
        k>>=1;
    }
    return C;
}
int main()
{
    ll k;
    while(scanf("%d%lld",&n,&k)!=EOF)
    {
        int i,j;
        mat A;
        memset(A.m,0,sizeof(A.m));
        for(i=0;i<n;i++)
        scanf("%d",&A.m[0][i]);
        mat Q=magic(k);
        A=multi(A,Q);
        for(i=0;i<n;i++)
        {
            printf("%d",A.m[0][i]%100);
            if(i!=n-1) printf(" ");
        }
        printf("\n");
        
    }
    return 0;
} 

 

快速矩阵幂