CodeForces Gym 100735B 矩阵快速幂

先给出你前N个数来,a1,a2,a3,,,,an

再给出C个数,k1,k2,,,kc,C<=N,1<=ki<=N,

然后对于后面的数,第i个数为ai=a(i-k1)+a(i-k2)+...+a(i-kc),然后让你求第M个数,M<=1e18

这个通项公式显然是很类似斐波那契数的,斐波那契可以通过矩阵去求,这个显然也可以,

然后就是构造出那样一个矩阵来,矩阵快速幂就行

#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
using namespace std;
#define ll long long
#define mod 1000000009
int N, C;
ll K;
ll init[30];
ll add[30];
ll ans[30][30], matrix[30][30];
ll tmp[30][30];
void work()
{
	for (int i = 0; i < N; ++i)
		tmp[i][i] = 0;
	for (int i = 0; i < N; ++i)
		ans[i][i] = 1;
	while (K)
	{
		if ((K & 1) > 0)
		{
			for (int i = 0; i < N; ++i)
			{
				for (int j = 0; j < N; ++j)
				{
					for (int k = 0; k < N; ++k)
						tmp[i][j] += (ans[i][k] * matrix[k][j]) % mod;
					tmp[i][j] %= mod;
				}
			}
			for (int i = 0; i < N; ++i)
			{
				for (int j = 0; j < N; ++j)
				{
					ans[i][j] = tmp[i][j];
					tmp[i][j] = 0;
				}
			}
		}
		for (int i = 0; i < N; ++i)
		{
			for (int j = 0; j < N; ++j)
			{
				for (int k = 0; k < N; ++k)
					tmp[i][j] += (matrix[i][k] * matrix[k][j]) % mod;
				tmp[i][j] %= mod;
			}
		}
		for (int i = 0; i < N; ++i)
		{
			for (int j = 0; j < N; ++j)
			{
				matrix[i][j] = tmp[i][j];
				tmp[i][j] = 0;
			}
		}
		K >>= 1;
	}
}
int main()
{
	//freopen("input.txt", "r", stdin);
	scanf("%d%I64d%d", &N, &K, &C);
	for (int i = 0; i < N; ++i)
		scanf("%I64d", &init[i]);
	for (int i = 0; i < C; ++i)
		scanf("%I64d", &add[i]);
	for (int i = 1; i < N; ++i)
	{
		matrix[i][i - 1] = 1;
	}
	for (int i = 0; i < C; ++i)
	{
		matrix[0][add[i] - 1] = 1;
	}
	/*for (int i = 0; i < N; ++i)
	{
		for (int j = 0; j < N; ++j)
			printf("%I64d ", matrix[i][j]);
		printf("\n");
	}*/
	ll sum = 0;
	if (K > N)
	{
		K -= N;
		work();
		for (int i = 0; i < N; ++i)
		{
			sum += (ans[0][i] * init[N - 1 - i]) % mod;
		}
		sum %= mod;
	}
	else
	{
		sum = init[K - 1];
	}
	printf("%I64d\n", sum);
	//system("pause");
	//while (1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值