タイムタイム T i m e L imit:制限:L i m i t: 3000 MS 3000MS3 0 0 0 M S
MのエモリーメモリM e m o r y L imit:制限:L i m i t: 131072 K 131072K1 3 1 0 7 2 K
説明
リンクリンク L I N kが
与えられるN×N-N×Nn××n行列AAAと正の整数kkk、合計を求めますS = A + A 2 + A 3 +…+ A k S = A + A ^ 2 + A ^ 3 +…+ A ^ kS=A+A2+A3+…+Ak。
入力
入力には、テストケースが1つだけ含まれています。入力の最初の行には、3つの正の整数n(n≤30)、k(k≤109)、およびm(m <104)が含まれています。次に、それぞれが32,768未満のn個の非負の整数を含むn行をたどり、Aの要素を行優先の順序で指定します。
出力
Aが与えられたのと同じ方法で、mを法とするSの要素を出力します。
サンプル入力
2 2 4
0 1
1 1
サンプル出力
1 2
2 3
分析:
直接計算では、時間外に行列[A i − 1、S i − 2] [A ^ {i-1}、S_ {i-2}]が考慮されます。[ Ai − 1、SI - 2]
[A i、S i − 1] = [A i − 1、S i − 2] ∗ F [A ^ i、S_ {i-1}] = [A ^ {i-1}、S_ {i- 2}] * F[ A私、SI - 1]=[ Ai − 1、SI - 2]∗F
FFFは変換行列、次にFFですF为:
A , E A,E A 、E
O、E O、E O 、E
其中 E E Eは単位行列 OOを表しますOはすべて000行列。SSを構築するには
、最初の行列構築を拡張する必要があることに注意してください。
Sは初期行列[1] [2] [1] [2]にあります[ 1 ] [ 2 ]
コード:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,mod,k;
struct matrix{
ll n,m;
ll F[101][101];
}A,B,C;
matrix operator *(matrix a,matrix b)
{
matrix c;
c.n=a.n;c.m=a.m;
for(int i=1;i<=c.n;i++)
for(int j=1;j<=c.m;j++)
c.F[i][j]=0;
for(int k=1;k<=a.m;k++)
for(int i=1;i<=c.n;i++)
for(int j=1;j<=c.m;j++)
c.F[i][j]=(c.F[i][j]+a.F[i][k]*b.F[k][j]%mod)%mod; //矩阵乘法
return c;
}
void ksm(ll x)
{
if(x==1){
B=A;
return;
}
ksm(x/2);
B=B*B;
if(x&1) B=B*A;
}
int main(){
scanf("%lld%lld%lld",&n,&k,&mod);
C.n=n;C.m=2*n;A.n=n*2;A.m=n*2;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%lld",&C.F[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
A.F[i][j]=C.F[i][j];
for(int i=1;i<=n;i++)
for(int j=n+1;j<=n+n;j++)
if(i+n==j) //赋单位矩阵
A.F[i][j]=1; //相当于初始矩阵[1][2]的初值
for(int i=n+1;i<=n+n;i++)
for(int j=n+1;j<=n+n;j++)
if(i==j) //同单位矩阵
A.F[i][j]=1; //初始矩阵[2][2]的初值
ksm(k);
C=C*B;
for(int i=1;i<=n;i++)
{
for(int j=n+1;j<=n+n;j++)
printf("%lld ",C.F[i][j]); //输出[1][2]
printf("\n");
}
return 0;
}