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

来源:互联网 发布:2016全国溺水事故数据 编辑:程序博客网 时间:2024/06/05 01:09
三个袋子

【题目描述】:

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

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

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

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

N   1   2   3    4    5   6    7     8     9      10M   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 longusing 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;}

原创粉丝点击