矩阵快速幂。。。顾名思义就是利用矩阵的结合律来进行快速幂运算。。。嘛,笔者也是做这道题两小时前把矩阵快速幂搞明白了的。。。所以其实还不熟= =
题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3690
首先我们的思路是建立矩阵的转换式,由题意可知在n个数中只有大于k的数字才能相邻,那么其实就是大于k的数字可以随便放啦。
所以令当前选择的数字大于k的部分为a,小于k的部分为b;则有:
| m-k m-k | | An | | An+1 |
| k k-1 | * | An+1 | = | An+2 | (原谅我不会画矩阵。。。)
然后就是这样,代码如下
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define LL long long using namespace std; struct mat { LL a,b; LL c,d; }ans,w; LL n,m,k; const int mod=1000000007; mat mix(mat a,mat b) { mat ans; ans.a=(a.a*b.a+a.b*b.c)%mod; ans.b=(a.a*b.b+a.b*b.d)%mod; ans.c=(a.c*b.a+a.d*b.c)%mod; ans.d=(a.c*b.b+a.d*b.d)%mod; return ans; } int main() { while(~scanf("%lld%lld%lld",&n,&m,&k)) { w.a=w.b=m-k; w.c=k; w.d=k-1; ans.a=ans.d=1; ans.b=ans.c=0; n--; while(n) { if(n&1) ans=mix(w,ans); w=mix(w,w); n=n>>1; //cout<<ans.a<<" "<<ans.b<<endl; //cout<<ans.c<<" "<<ans.d<<endl<<endl; } printf("%lld\n",((ans.a+ans.c)*(m-k)%mod+(ans.b+ans.d)*k%mod)%mod); } return 0; }