Codeforces 392C Yet Another Number Sequence

来源:互联网 发布:深圳国税网络开票软件 编辑:程序博客网 时间:2024/05/20 06:27

题目链接:http://codeforces.com/problemset/problem/392/C

题目简述:

F1 = 1, F2 = 2, Fi = Fi - 1 + Fi - 2 (i > 2).

We'll define a new number sequence Ai(k) by the formula:

Ai(k) = Fi × ik (i ≥ 1).

In this problem, your task is to calculate the following sum: A1(k) + A2(k) + ... + An(k). The answer can be very large, so print it modulo1000000007 (109 + 7).

 (1 ≤ n ≤ 1017; 1 ≤ k ≤ 40).


Then:

挺有意思的题。。。挺有意思。。真有意思。
如果我做这道题之前就写过什么矩阵递推总结。
这题很有启发性啊,就是因为这个题才让我有写那个东西的想法。

一看肯定是矩阵,然后呢?然后就真的没有然后了。


怎么构造转移矩阵。初始矩阵又是什么。根本不知道。

从头开始想吧, 如果有了AiK的递推,那求和肯定就不是问题(总结里写过)。
矩阵可以解决线性递推。
那么我们肯定要先把Ai(k)这个式子变成一个递推式,而不是通项。! 这是本题的关键啊!!!(当然只是我以为)
下面就考虑如何变形:

A_{i}(K)\\
=F_{i}*i^K \\
=(F_{i-1}+F_{i-2})*i^K\\
=F_{i-1}*i^K+F_{i-2}*i^K\\
=F_{i-1}*[(i-1)+1]^K+F_{i-2}*[(i-2)+2]^K\\
=\sum_{j=0}^{K} {\binom{K}{j}*F_{i-1}*(i-1)^j}+\sum_{j=0}^{K} {\binom{K}{j}*2^{K-j}*F_{i-2}*(i-2)^j}\\
=\sum_{j=0}^{K} {\binom{K}{j}*A_{i-1}(j)}+\sum_{j=0}^{K} {\binom{K}{j}*2^{K-j}*A_{i-2}(j)}\\

然后我们就得到了一个Ai(k)的递推式。
考虑怎么建立初始矩阵:

这样的矩阵才能记录完信息,
我最开始竟然建成两行,是不是沙茶。 两行怎么推。
转移矩阵是2*K+1的,
系数在上面的式子已经很清楚了,都是些组合数或者组合数乘2的幂。
不方便打出来啊。。太难打了。。

然后就是代码实现的问题了。。
像我这样建立矩阵,恶心到死。
哎,反正建立矩阵超级恶心啊,后面都不是事儿了。
#include <cstdio>#include <cstring>#include <algorithm>#define rep(i,l,r) for (int i=l;i<=r;++i)#define per(i,r,l) for (int i=r;i>=l;--i)typedef long long LL;const LL MOD=1000000007;const int MAX_K=45;struct Matrix{LL a[MAX_K*2][MAX_K*2],n,m;Matrix(int _n = 0,int _m = 0):n(_n),m(_m){rep(i,1,n)rep(j,1,m) a[i][j]=0;}void dw(int _n,int _m){n=_n,m=_m;rep(i,1,n)rep(j,1,m) a[i][j]=(i==j?1:0);}LL& operator ()(int i,int j){return a[i][j];}void print(){rep(i,1,n) rep(j,1,m) printf("%I64d%c",a[i][j],j==m?'\n':' ');}};Matrix operator *(Matrix a,Matrix b){Matrix res(a.n,b.m);rep(i,1,a.n) rep(j,1,b.m) rep(k,1,a.m)(res(i,j)+=a(i,k)*b(k,j))%=MOD;return res;}Matrix operator ^(Matrix a,LL x){Matrix res;res.dw(a.n,a.m);for (;x;a=a*a,x>>=1)if (x&1) res=res*a;return res;}LL pow2[MAX_K*2];LL c[MAX_K*2][MAX_K*2];void getC(int x){c[0][0]=1;pow2[0]=1;rep(i,1,x){c[i][0]=1;pow2[i]=(pow2[i-1]*2)%MOD;rep(j,1,i) c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;}}LL n,k;int main(){scanf("%I64d%I64d",&n,&k);getC(k);Matrix a(1,2*k+3),dp(2*k+3,2*k+3);//rep(i,1,k+1) a(1,i)=1;rep(i,1,k+1) a(1,i)=2*pow2[k-i+1];rep(i,k+2,2*k+2) a(1,i)=1;a(1,2*k+3)=1;rep(i,1,k+1) rep(j,1,i) dp(i,j)=c[k-j+1][k-i+1];rep(i,k+2,2*k+2) rep(j,1,i-(k+1))dp(i,j)=pow2[i-(k+1)-1-(j-1)]*c[k-j+1][k-(i-(k+1))+1]%MOD;//rep(i,1,k+1) rep(j,1,k-(i-1)+1) dp(i,j)=c[k-j+1][i-1];//rep(i,k+2,2*k+2) rep(j,1,k-(i-(k+1)-1)+1)//dp(i,j)=(pow2[k-(i-(k+1)-1)-(j-1)]*c[k-j+1][i-(k+1)-1])%MOD;rep(i,k+2,2*k+2) dp(i-(k+1),i)=1;dp(1,2*k+3)=dp(2*k+3,2*k+3)=1;//dp.print();//a.print();a=a*(dp^(n-1));//a.print();printf("%I64d\n",a(1,2*k+3));}


总结下吧:

矩阵递推,当然要求出递推式。。然后问题就迎刃而解了。

0 0
原创粉丝点击