/*
题目: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;
}