【SDOI 2008】 遞歸數列

【題目鏈接】

          點擊打開鏈接

【算法】

          矩陣乘法優化遞推

          由於本博客不支持數學公式,所以不能將矩陣畫出來,請諒解!

【代碼】

         

#include<bits/stdc++.h>
using namespace std;
#define MAXK 18

struct Matrix 
{
		long long mat[MAXK][MAXK];
};

int i,k;
long long n,m,p,sum;
long long b[MAXK],c[MAXK];

template <typename T> inline void read(T &x)
{
    long long f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
template <typename T> inline void write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9) write(x/10);
    putchar(x%10+'0');
}
template <typename T> inline void writeln(T x)
{
    write(x);
    puts("");
}

inline void multipy(Matrix &a,Matrix b)
{
		int i,j,t;
		Matrix ans;
		memset(ans.mat,0,sizeof(ans.mat));
		for (i = 1; i <= k + 1; i++)
		{
				for (j = 1; j <= k + 1; j++)
				{
						for (t = 1; t <= k + 1; t++)
						{
								ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][t] * b.mat[t][j]) % p;
						}
				}
		}
		a = ans;
}
inline long long solve(long long n)
{
		Matrix a,res;
		int i,j;
		long long ans = 0;
		memset(a.mat,0,sizeof(a.mat));
		for (i = 2; i <= k + 1; i++) a.mat[1][i] = a.mat[2][i] = c[i-1];
		for (i = 3; i <= k + 1; i++) a.mat[i][i-1] = 1;
		a.mat[1][1] = 1;
		memset(res.mat,0,sizeof(res.mat));
		for (i = 1; i <= k + 1; i++) res.mat[i][i] = 1;
		while (n > 0)
		{
				if (n & 1) multipy(res,a);
				multipy(a,a);
				n >>= 1;
		}
		ans = sum;
		for (i = 2; i <= k + 1; i++) ans = (ans + res.mat[1][i] * b[k-i+2]) % p;
		return ans;
}
inline long long query(long long n)
{
		int i;
		long long ans = 0;
		if (n <= k)
		{
				for (i = 1; i <= n; i++) ans = (ans + b[i]) % p;
				return ans;
		} else return solve(n-k);
}

int main() {
		
		read(k);
		for (i = 1; i <= k; i++) read(b[i]);
		for (i = 1; i <= k; i++) read(c[i]);
		read(m); read(n); read(p);
		for (i = 1; i <= k; i++) sum = (sum + b[i]) % p;
		writeln((query(n) - query(m-1) + p) % p);
		
		return 0;
	
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章