ZOJ3690Choosing number
来源:互联网 发布:免费数据采集器 编辑:程序博客网 时间:2024/05/22 12:43
/*
题目:Choosing number
题目连接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3690
题目大意:
n个人站成一行,这儿有m个数字,1,2...m,每个人选择一个数字,但是如果相邻的两个人选择了同一个数字
这个数字不能超过k,请问他们有多少种选择数字的方式?
解题思路:
我们一个人一个人的考虑,且从前往后,设两个函数G(i),F(i),G(i)表示前i-1个人选好后第i个人选择小于等于k数字时
的方案数,F(i)表示前i-1个人选好后第i个人选择大于k数字时的方案数,那我们得G(1)=k,F(1)=m-k;
G(i)=F(i-1)*k+G(i-1)*(k-1);
当第i-1个人选大于k的数字时,第i个人可以选择1-k的任意数,所以加上F(i-1)*k,
而当第i-1个人选小于等k的数字时,第i个人只要不和他选择的一样就可以了所以有(k-1)种情况;
又因为选择1-k里面每个数字时等概率的,所以最后加上G(i-1)*(k-1);
F(i)=(F(i-1)+G(i-1))*(m-k);
当第i个人选大于k的数字时,第i-1个人可以任意选;
得到这个递推式后,我们可以构造一个转移矩阵得:
[F[i]] [m-k,m-k ] [F[i-1]]
[G[i]]=[k,(k-1)/k] × [G[i-1]]
然后用矩阵快速幂加速运算,最后的结果就是F(n)+G(n);
题目:Choosing number
题目连接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3690
题目大意:
n个人站成一行,这儿有m个数字,1,2...m,每个人选择一个数字,但是如果相邻的两个人选择了同一个数字
这个数字不能超过k,请问他们有多少种选择数字的方式?
解题思路:
我们一个人一个人的考虑,且从前往后,设两个函数G(i),F(i),G(i)表示前i-1个人选好后第i个人选择小于等于k数字时
的方案数,F(i)表示前i-1个人选好后第i个人选择大于k数字时的方案数,那我们得G(1)=k,F(1)=m-k;
G(i)=F(i-1)*k+G(i-1)*(k-1);
当第i-1个人选大于k的数字时,第i个人可以选择1-k的任意数,所以加上F(i-1)*k,
而当第i-1个人选小于等k的数字时,第i个人只要不和他选择的一样就可以了所以有(k-1)种情况;
又因为选择1-k里面每个数字时等概率的,所以最后加上G(i-1)*(k-1);
F(i)=(F(i-1)+G(i-1))*(m-k);
当第i个人选大于k的数字时,第i-1个人可以任意选;
得到这个递推式后,我们可以构造一个转移矩阵得:
[F[i]] [m-k,m-k ] [F[i-1]]
[G[i]]=[k,(k-1)/k] × [G[i-1]]
然后用矩阵快速幂加速运算,最后的结果就是F(n)+G(n);
*/
#include<stdio.h>#include<string.h>#ifdef _WIN32#define _LL __int64#define _FIN "%I64d"#else #define _LL long long#define _FIN "%lld"#endif#define mod 1000000007_LL m,k;void init(_LL x[2][2]){x[0][0]=x[0][1]=m-k;x[1][0]=k;x[1][1]=(k-1);}void mult(_LL x[2][2],_LL y[2][2]){int i,j,k;_LL c[2][2];for(i=0;i<2;i++){for(j=0;j<2;j++){c[i][j]=0;for(k=0;k<2;k++)c[i][j]=(c[i][j]+(x[i][k]*y[k][j])%mod)%mod;}}for(i=0;i<2;i++) for(j=0;j<2;j++) x[i][j]=c[i][j];}_LL power(_LL y){_LL ans;_LL sum[2][2]={1,0,0,1};_LL x[2][2];init(x);while(y){if(y&1)mult(sum,x);mult(x,x);y>>=1;}ans=(sum[0][0]*(m-k)%mod+sum[0][1]*k%mod)%mod;ans=(ans+(sum[1][0]*(m-k))%mod+(sum[1][1]*k)%mod)%mod;return ans;}int main(){_LL n;while(scanf(_FIN,&n)!=EOF){scanf(_FIN,&m);scanf(_FIN,&k);if(n==1) printf(_FIN,m);else printf(_FIN,power(n-1));printf("\n");}return 0;}
- ZOJ3690Choosing number
- ZOJ3690Choosing number
- zoj3690Choosing number 矩阵dp
- Number
- number
- number
- Number
- number
- number
- Number
- Number
- NUMBER
- Number
- Number()
- number
- Number
- Number
- E: number number number
- IP包头部格式解析
- MySql函数
- 802.11n兼容a/b/g问题(Legacy mode,Mixed mode,Greenfield mode)
- [Python]用一行 map,reduce 计算 5!+4!+3!+2!+1!
- poj1458解题报告
- ZOJ3690Choosing number
- 黑马程序员-------JavaIO流
- HDU 1671 Phone List
- 解决 ASP.NET 中 System.OutOfMemoryException 的问题
- 学生类
- 几种开源TCPIP协议概述--LwIP,uIP,TinyTcp和uC/IP
- 5-2 分数类
- nessus5 的种种
- make&Makefile