题意就是:
有n个人,每个人可以从m个数中选取其中的一个数,而且如果两个相邻的数相同,则这个数不能超过k,问这样的数一共有多少种选择,结果取模。
思路:
我们用 f[i]表示第i个位置大于k的种数,用g[i]表示第i个数小于等于k的种数。则最终的答案就是(f[i]+g[i])%mod。
f[i] =f[i-1]*(m-k)+g[i-1]*(m-k);
g[i]=f[i-1]*k+g[i-1]*(k-1);
因为n的值很大,所以我们得用矩阵快速幂来求解。
矩阵: k-1 m-k
k m-k
初始矩阵为:
0 1
0 0
代码:
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
#define LL long long
#define MOD 1000000007
struct node {
LL val[2][2];
};
node Init;
node ans;
LL n,m,k;
void init() {
Init.val[0][0] = 0;
Init.val[0][1] = 1;
Init.val[1][0] = 0;
Init.val[1][1] = 0;
ans.val[0][0] = k - 1;
ans.val[0][1] = m - k;
ans.val[1][0] = k;
ans.val[1][1] = m - k;
}
node Mul(node a,node b) {
node tmp;
for(int i = 0; i < 2; i ++) {
for(int j = 0; j < 2; j ++) {
tmp.val[i][j] = 0;
for(int k = 0; k < 2; k ++) {
tmp.val[i][j] += (a.val[i][k] * b.val[k][j]) % MOD;
tmp.val[i][j] %= MOD;
}
}
}
return tmp;
}
void solve() {
init();
while(n) {
if(n & 1) {
Init = Mul(Init,ans);
}
ans = Mul(ans,ans);
n >>= 1;
}
LL ANS = 0;
ANS = (Init.val[0][0] + Init.val[0][1]) % MOD;
cout<<ANS<<endl;
}
int main() {
while(cin>>n>>m>>k) {
solve();
}
return 0;
}