【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;
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值