题目链接: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)|
f[n]= | | * | |
|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)|
不难推出:
f[n]= | | * | |
|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;
}