递推的矩阵乘法解决练习1

三个袋子

【题目描述】:

平平在公园里游玩时捡到了很多小球,而且每个球都不一样。平平找遍了全身只发现了3个一模一样的袋子。他打算把这些小球都装进袋子里(袋子可以为空)。他想知道他总共有多少种放法。

将N个不同的球放到3个相同的袋子里,求放球的方案总数M。

结果可能很大,我们仅要求输出M mod K的结果。

现在,平平已经统计出了N<=10的所有情况。见下表:

N   1   2   3    4    5   6    7     8     9      10

M   1   2   5   14   41  122  365   1094  3281   9842

【输入描述】:

两个整数N,K,N表示球的个数。

【输出描述】:

输出仅包括一行,一个整数M mod K 。

【样例输入】:

11 10000

【样例输出】:

9525

【时间限制、数据范围及描述】:

时间:1s 空间:64

对于 40%数据,10<=N<=10,000

对于100%数据,10<=N<=1,000,000,000

对于 100%数据,K<=100,000.


这题需要我们先把递推公式找出来。不难发现F[i]=F[i-1]*3-1。但是如果用O(N)的算法枚举的话肯定会超时,那么在这种情况下我们只能用矩阵乘法来解决了。这个矩阵x得出来就是3 0,再用矩阵快速幂求这个矩阵的n-1次方就是答案了
                                                                                                -1 1

AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
int mod;
struct jz{
	ll x[5][5];
};
jz mult(jz a,jz b){
	jz c;
	memset(c.x,0,sizeof(c.x));
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			for(int k=0;k<2;k++){
				c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j]+mod)%mod; 
			}
		}
	}
	return c;
}
jz qpow(jz m,int n){
	jz mul;
	mul.x[0][0]=1;
	mul.x[1][1]=1;
	mul.x[0][1]=0;
	mul.x[1][0]=0;
	while(n){
		if(n&1){
			mul=mult(mul,m);
		}
		n>>=1;
		m=mult(m,m);
	} 
	return mul;
}
int main(){
	int n;
	jz s0,ans;
	s0.x[0][0]=3;s0.x[0][1]=0;s0.x[1][0]=-1;s0.x[1][1]=1;
	scanf("%d%d",&n,&mod);
	ans=qpow(s0,n-1);
	printf("%lld\n",(ans.x[0][0]+ans.x[1][0]+mod)%mod);
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值