[TIOJ] 1331. 索拉數列

題目連結:http://tioj.infor.org/problems/1331
看一眼大概就可以發現這就是一個經典的矩陣優化DP的題目,稍微算一下後得到轉移矩陣$ \begin{bmatrix} 0 & x \\ 1 & y \\ \end{bmatrix} $,所以要求$a_n$其實就是算$ \begin{bmatrix} a_0 & a_1 \\ \end{bmatrix} \times \begin{bmatrix} 0 & x \\ 1 & y \\ \end{bmatrix}^n = \begin{bmatrix} a_n & a_{n+1} \\ \end{bmatrix}$ ,然後冪次的部分用快速冪解決。
#include <bits/stdc++.h>
using namespace std;
typedef long long lld;
typedef unsigned long long llu;

const llu mod = 1LL<<32;
auto A = new llu[2][2];
auto B = new llu[2][2];
auto C = new llu[2][2];
auto F = new llu[2][2];

void mTimes(llu[2][2],llu[2][2],llu[2][2],int,int,int);

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	lld n, a, b, x, y;
	while(cin>>n, n>=0){
		cin>>a>>b>>x>>y;
		F[0][0]=a;
		F[0][1]=b;
		A[0][0]=0;
		A[0][1]=x;
		A[1][0]=1;
		A[1][1]=y;
		B[0][0]=1;
		B[0][1]=0;
		B[1][0]=0;
		B[1][1]=1;
		while(n>0){
			if(n&1){
				mTimes(A,B,C,2,2,2);
				swap(C,B);
			}
			n>>=1;
			mTimes(A,A,C,2,2,2);
			swap(A, C);
		}
		C[0][0]=(((F[0][0]*B[0][0])%mod)+((F[0][1]*B[1][0])%mod))%mod;
		cout<<(lld)C[0][0]<<'\n';
	}
	return 0;
}

void mTimes(llu a[2][2], llu b[2][2], llu c[2][2], int x, int y, int z){
	for(int i=0;i<x;i++){
		for(int j=0;j<z;j++){
			c[i][j]=0;
			for(int k=0;k<y;k++)
				c[i][j] += (a[i][k]*b[k][j])%mod;
			c[i][j]%=mod;
		}
	}
}

留言

這個網誌中的熱門文章

[NPSC] 2009初賽 E. 檸檬汽水傳說

[TIOJ] 1902. 「殿仁.王,不認識,誰啊?」,然後他就死了……

[AtCoder] [經典競程 90 題] 024 - Select +/- One(★2)