ZOJ 3690 矩阵快速幂乘
2013-04-14 01:02
27 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3690
题意:有n个人站在一排,另外有m个号码,每个人都选其中的一个号码,但是有一个条件是,如果两个相邻人选了相同的号码,那么这个号码要大于k;问一共有多少种不同的选法
思路:
1 2 3 4 .......表示站第n的人
|-k...........
|--(k-1)-|
| |(m-k)........
|--k-| |--k ..........
| |--(m-k)|
| |(m-k).........
|
| |-(k-1)........
| |--k--|
|(m-k)-| |-(m-k).......
|
| |--k..........
|(m-k)|
|(m-k).........
答案肯定是这些一条条链乘起来再相加了,问题是怎么算呢?
可以看到每个k后面都是(k-1),(m-k),每个(m-k)和(k-1)后面都是(m-k)
第一次时令a=m-k, b=k; f[2] = (a+b)*(m-k) + (a*k+b*(k-1)) ;
第二次时令a=(a+b)*(m-k), b=(a*k+b*(k-1)); 则f[3]= (a+b)*(m-k) + (a*k+b*(k-1))
第三次........
发现了没,这些式子是一样的,这是不是又想到了两个2*2的矩阵乘法呢?
|(m-k) k| |(m-k) k |
f[2]= | | * | |
|0 0| |(m-k) (k-1)|
不难推出:
|(m-k) k| |(m-k) k | ^(n-1)
f
= | | * | |
|0 0| |(m-k) (k-1)|
接下来用矩阵幂乘就可以了!!
题意:有n个人站在一排,另外有m个号码,每个人都选其中的一个号码,但是有一个条件是,如果两个相邻人选了相同的号码,那么这个号码要大于k;问一共有多少种不同的选法
思路:
1 2 3 4 .......表示站第n的人
|-k...........
|--(k-1)-|
| |(m-k)........
|--k-| |--k ..........
| |--(m-k)|
| |(m-k).........
|
| |-(k-1)........
| |--k--|
|(m-k)-| |-(m-k).......
|
| |--k..........
|(m-k)|
|(m-k).........
答案肯定是这些一条条链乘起来再相加了,问题是怎么算呢?
可以看到每个k后面都是(k-1),(m-k),每个(m-k)和(k-1)后面都是(m-k)
第一次时令a=m-k, b=k; f[2] = (a+b)*(m-k) + (a*k+b*(k-1)) ;
第二次时令a=(a+b)*(m-k), b=(a*k+b*(k-1)); 则f[3]= (a+b)*(m-k) + (a*k+b*(k-1))
第三次........
发现了没,这些式子是一样的,这是不是又想到了两个2*2的矩阵乘法呢?
|(m-k) k| |(m-k) k |
f[2]= | | * | |
|0 0| |(m-k) (k-1)|
不难推出:
|(m-k) k| |(m-k) k | ^(n-1)
f
= | | * | |
|0 0| |(m-k) (k-1)|
接下来用矩阵幂乘就可以了!!
#include<iostream> #include<string> #include<cstring> #include<algorithm> #include<cstdio> #include<cmath> #include<cctype> #include<iomanip> using namespace std; typedef long long ll; const int mod=1000000007; struct Matrix { ll x, y; ll z, w; } R,M; Matrix multi( Matrix A, Matrix B ) { Matrix Z; Z.x = (A.x*B.x+A.y*B.z)%mod; Z.y = (A.x*B.y+A.y*B.w)%mod; Z.z = (A.z*B.x+A.w*B.z)%mod; Z.w = (A.z*B.y+A.w*B.w)%mod; return Z; } void calc(int n){ /// M = R^n; M=R; while(n){ if(n&1) M=multi(M,R); n>>=1; R=multi(R,R); } } int main() { int n,m,k; while(cin>>n>>m>>k) { R.x = R.z = m-k; R.y = k; R.w = k-1; calc( n-2 ); ll ans =( (m-k)*M.x + k*M.z + (m-k)*M.y + k*M.w )%mod ; cout<< ans <<endl; } return 0; }
相关文章推荐
- JSP快速入门教程——全十讲
- Hadoop快速入门
- lucene,你也会(7篇)——第一篇 快速入门
- 提取拼音首字母 在很多软件中,输入拼音的首写字母就可以快速定位到某个词条。
- 感慨一下发展快速的前端开发
- OceanBase 快速入门_3 源码结构
- 算法实现-->快速排序
- [HDU 3306] Another kind of Fibonacci · 矩阵快速幂
- OpenStack云计算快速入门之二:OpenStack安装与配置
- 简单快速打造你自己的PHP MVC框架
- Vivado HLS IP-XACT快速创建AXI总线IP(PWM)z
- PHP 实现快速排序
- 51nod 1113 矩阵连乘快速幂模板 (对100000007取模)
- Zookeeper 快速入门(上)
- 前端框架之Bootstrap快速开发
- 快速查找中位数 - 基于ANSI C的实现
- JQuery快速学习方法总结
- shell如何快速锁定所有账号
- Hashtable快速查找的方法
- STL 快速排序