HDU - 6185 Covering

思路

类似插头dp的题,但数据范围到了10^18次。我们发现他的宽度只有4,若我们令a[n]为方案数,b[n]为不可分割的矩阵数,通过打表我们能发现a[1]=b[1]=1,b[2]=4,且n>=3时有:
当n为奇数时:b[n]=2
当n为偶数时:b[n]=3
我的理解是更多分割的方案在之前已经有过计算,所以只有把原有的矩阵拉长的方案没有计算过,我们使用递推式计算就是要使用这一部分。
最后计算可得a[n]=a[n-1]+5a[n-2]+a[n-3]-a[n-4],然后使用矩阵快速幂。

参考

POJ3420 递推/状态压缩DP +矩阵幂加速处理

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <bits/stdc++.h>
#define ll long long
#define INF 0x7fffffff
#define lson(x) (x<<1)
#define rson(x) ((x<<1)|1)
#define ms(a,val) memset((a),(val),(sizeof(a)))

using namespace std;

const int MAXN=5;
const int MOD=1000000007;

//Matrix class
struct Mat {
int n, m;
ll num[MAXN][MAXN];
Mat(int n = MAXN, int m = MAXN) :n(n), m(m) { ms(num, 0); };
Mat operator +(const Mat &b)const {
Mat ans(n, m);
for (int i = 0;i<n;i++) {
for (int j = 0;j<m;j++) {
ans.num[i][j] = num[i][j] + b.num[i][j];
}
}
return ans;
}
Mat operator -(const Mat &b)const {
Mat ans(n, m);
for (int i = 0;i<n;i++) {
for (int j = 0;j<m;j++) {
ans.num[i][j] = num[i][j] - b.num[i][j];
}
}
return ans;
}
Mat operator *(const Mat &b)const {
Mat ans(n, b.m);
for (int i = 0;i<n;i++) {
for (int j = 0;j<b.m;j++) {
for (int k = 0;k<m;k++) {
ans.num[i][j] = ((ans.num[i][j] + num[i][k] * b.num[k][j]) % MOD+MOD)%MOD;
}
}
}
return ans;
}
Mat getI(int x) {
Mat ans(x, x);
for (int i = 0;i<x;i++)ans.num[i][i] = 1;
return ans;
}
void pow(ll x) {
Mat I = getI(4);
ll cal = x;
while (cal) {
if (cal & 1) {
I = I*(*this);
cal--;
}
(*this) = (*this)*(*this);
cal /= 2;
}
(*this) = I;
}
};

int main() {
ll n;
while(~scanf("%I64d",&n)){
Mat A,B;
A.num[0][0]=(ll)1,A.num[0][1]=(ll)5,A.num[0][2]=(ll)1,A.num[0][3]=(ll)(-1),A.num[1][0]=(ll)1,A.num[2][1]=(ll)1,A.num[3][2]=(ll)1;
B.num[0][0]=(ll)36,B.num[1][0]=(ll)11,B.num[2][0]=(ll)5,B.num[3][0]=(ll)1;
if(n<=4)printf("%lld\n",B.num[4-n][0]);
else{
A.pow(n-4);
Mat ans=A*B;
printf("%lld\n",ans.num[0][0]);
}
}
return 0;
}