题目链接:http://www.ifrog.cc/acm/problem/1031
题意:6个水果中挑出n个,使得其中2个水果个数必须是偶数,问有多少种选择方法。
设中0代表偶数,1代表奇数。分别代表两种水果的奇偶情况,有如下递推式:
初始化的矩阵为:
) 以后写题解就用latex编辑公式了QAQ
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const LL mod = (LL)1e9+7; 7 const int maxn = 5; 8 LL n; 9 typedef struct Matrix { 10 LL m[maxn][maxn]; 11 int r; 12 int c; 13 Matrix(){ 14 r = c = 0; 15 memset(m, 0, sizeof(m)); 16 } 17 } Matrix; 18 Matrix mul(Matrix m1, Matrix m2) { 19 Matrix ans = Matrix(); 20 ans.r = m1.r; 21 ans.c = m2.c; 22 for(int i = 1; i <= m1.r; i++) { 23 for(int j = 1; j <= m2.r; j++) { 24 for(int k = 1; k <= m2.c; k++) { 25 if(m2.m[j][k] == 0) continue; 26 ans.m[i][k] = ((ans.m[i][k] + m1.m[i][j] * m2.m[j][k] % mod) % mod) % mod; 27 } 28 } 29 } 30 return ans; 31 } 32 33 Matrix quickmul(Matrix m, LL n) { 34 Matrix ans = Matrix(); 35 for(int i = 1; i <= m.r; i++) { 36 ans.m[i][i] = 1; 37 } 38 ans.r = m.r; 39 ans.c = m.c; 40 while(n) { 41 if(n & 1) { 42 ans = mul(m, ans); 43 } 44 m = mul(m, m); 45 n >>= 1; 46 } 47 return ans; 48 } 49 50 int main() { 51 // freopen("in", "r", stdin); 52 int T, _ = 1; 53 scanf("%d", &T); 54 while(T--) { 55 scanf("%lld",&n); 56 Matrix a; a.r = 4; a.c = 1; 57 a.m[1][1] = 4; a.m[2][1] = 1; a.m[3][1] = 1; a.m[4][1] = 0; 58 Matrix p; p.r = 4, p.c = 4; 59 p.m[1][1] = 4; p.m[1][2] = 1; p.m[1][3] = 1; p.m[1][4] = 0; 60 p.m[2][1] = 1; p.m[2][2] = 4; p.m[2][3] = 0; p.m[2][4] = 1; 61 p.m[3][1] = 1; p.m[3][2] = 0; p.m[3][3] = 4; p.m[3][4] = 1; 62 p.m[4][1] = 0; p.m[4][2] = 1; p.m[4][3] = 1; p.m[4][4] = 4; 63 Matrix q = quickmul(p, n-1); 64 Matrix b = mul(q, a); 65 printf("Case #%d: %lld ", _++,b.m[1][1]); 66 } 67 return 0; 68 }