UVA 10870再発(Matrix Fast Power)

nは大きすぎて直接再帰できないため、行列の高速パワーで解く必要があります。時間の複雑さはO(d ^ 3logn)です。たとえば
    、d = 5の行列の関係は次のとおりです:
                | a1 a2 a3 a4 a5 | | f [n -1] | | f [n] |  
                | 1 | | f [n-2] | | f [n-1] |  
                | 1 | * | f [n-3] | = | f [n-2] | (空白は0)
                | 1 | | f [n-4] | | f [n-3] |
                | 1 | | f [n-5] |

F(n)= A * F(n-1);

したがって、F(n)= A ^(nd)* F(d);

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=20;
struct Mat{
	ll mat[N][N];
}sta,fi;
ll d,mod;
ll n,m;
Mat mul(Mat a,Mat b){
	Mat temp;
	memset(temp.mat,0,sizeof(temp.mat));
	for(int i=1;i<=d;i++)
	for(int j=1;j<=d;j++)
	for(int k=1;k<=d;k++)
	{
		temp.mat[i][j]=(temp.mat[i][j]+(a.mat[i][k]*b.mat[k][j])%m)%m;
	}
	return temp;
}

Mat quick(ll k){
	Mat temp;
	memset(temp.mat,0,sizeof(temp.mat));
	for(int i=1;i<=20;i++)
	temp.mat[i][i]=1;
	
	while(k){
		if(k&1)
		temp=mul(temp,sta);
		k>>=1;
		sta=mul(sta,sta);
	} 
	return temp;
}


int main(){
	while(~scanf("%d %lld %lld",&d,&n,&m)){
		memset(sta.mat,0,sizeof(sta.mat));
    	memset(fi.mat,0,sizeof(sta.mat));
		for(int i=2;i<=d;i++)
		sta.mat[i][i-1]=1;
		
		for(int i=1;i<=d;i++){
			scanf("%lld",&sta.mat[1][i]);
			sta.mat[1][i]%=m;
		}
		
		for(int i=1;i<=d;i++){
			scanf("%lld",&fi.mat[d-i+1][1]);
			fi.mat[d-i+1][1]%=m;
		}
		if(n<=(ll)d){
            printf("%lld\n",fi.mat[d-n+1][1]);
            continue;
        }
		fi=mul(quick(n-d),fi);
		printf("%lld\n",fi.mat[1][1]);
	}
}

 

公開された75元の記事 ウォン称賛77 ビュー4017

おすすめ

転載: blog.csdn.net/weixin_43568895/article/details/105479199