Choosing number
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld
& %llu
Description
There are n people standing in a row. And There are m numbers, 1.2...m. Every one should choose a number. But if two persons standing adjacent to each other choose the same number, the number shouldn‘t equal or less than k.
Apart from this rule, there are no more limiting conditions.
And you need to calculate how many ways they can choose the numbers obeying the rule.
Input
There are multiple test cases. Each case contain a line, containing three integer n (2 ≤ n ≤ 108), m (2 ≤ m ≤ 30000), k(0 ≤ k ≤ m).
Output
One line for each case. The number of ways module 1000000007.
Sample Input
4 4 1
Sample Output
216
题意:n个人每个人在m个数中选一个,要求相邻的人如果数字相同,那么数字要大于k,问有多少种选法
dp[i][0] 代表有i个人时 且最后一个人选的数小于等于k的种数
dp[i][0] 代表有i个人时 且最后一个人选的数大于k的种数
用矩阵快速幂的优化和http://blog.csdn.net/winddreams/article/details/42805891相同
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #define LL long long #define MOD 1000000007 struct node { LL a[5][5] ; int n ; }; node mul(node p,node q) { int i , j , k ; node s ; s.n = p.n ; for(i = 0 ; i < p.n ; i++) for(j = 0 ; j < p.n ; j++) { s.a[i][j] = 0 ; for(k = 0; k < p.n ; k++) s.a[i][j] = ( s.a[i][j] + p.a[i][k]*q.a[k][j] ) % MOD ; } return s ; } node pow(node p,int k) { if( k == 1 ) return p ; node s = pow(p,k/2) ; s = mul(s,s) ; if( k%2 ) s = mul(s,p) ; return s ; } int main() { LL n , m , k , ans ; int i , j ; node p , s ; while( scanf("%lld %lld %lld", &n, &m, &k) != EOF ) { ans = 0 ; p.n = 2; p.a[0][0] = k-1 ; p.a[0][1] = k ; p.a[1][0] = m-k ; p.a[1][1] = m-k ; s = pow(p,n-1) ; ans = ( ans + s.a[0][0]*k + s.a[1][0]*k ) % MOD ; ans = ( ans + s.a[0][1]*(m-k) + s.a[1][1]*(m-k) ) % MOD ; printf("%lld\n", ans) ; } return 0; }