[AHOI2004]数字迷阵
瞪眼观察题。发现行列都跟斐波那契数列有关。
如果能求出第一列就好了。
发现第一列的数都是由若干个$2$和若干$3$的和加$1$。
发现第$fib[i]$行有$fib[i-2]$个3和$fib[i-3]$个2。
其他行呢?
将行号拆分成若干项斐波那契数列的和,发现对应的$3$、$2$的数目也是对应的和。
然后万事大吉了。
距离$AC$还只需要会矩阵快速幂。
感性理解代码。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define For(i, a, b, s) for (re int i = a; i <= b; s) 9 #define maxx(a, b) a = max(a, b) 10 #define minn(a, b) a = min(a, b) 11 #define LL long long 12 #define INF (1 << 30) 13 14 inline int read() { 15 int w = 0, f = 1; char c = getchar(); 16 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 17 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 18 return w * f; 19 } 20 21 const int MAX = 1000000000; 22 23 struct Matrix { 24 int a, b, c, d; 25 // | a b | 26 // | c d | 27 } f, g; 28 29 int fib[100], x, y, P; 30 int a, b; 31 32 Matrix operator * (Matrix a, Matrix b) { 33 Matrix res; 34 res.a = (a.a * b.a + a.b * b.c) % P; 35 res.b = (a.a * b.b + a.b * b.d) % P; 36 res.c = (a.c * b.a + a.d * b.c) % P; 37 res.d = (a.c * b.b + a.d * b.d) % P; 38 return res; 39 } 40 41 int main() { 42 fib[1] = fib[2] = 1; 43 int X = x = read()-1; y = read(), P = read(); 44 int i; 45 for (i = 3; fib[i-1] <= x; i++) fib[i] = fib[i-1] + fib[i-2]; 46 while (i--) 47 if (fib[i] <= x) x -= fib[i], a = (a + 3 * fib[i-1]) % P, b = (b + 2 * fib[i-2]) % P; 48 a = (a+b+1) % P, b = (a*2ll+(LL)X*P-X) % P; 49 if (y < 3) printf("%d", y == 1 ? a : b); 50 else { 51 g.a = g.b = g.c = 1; g.d = 0; 52 f.a = f.d = 1; f.b = f.c = 0; 53 y -= 2; 54 while (y) { 55 if (y & 1) f = f * g; 56 g = g * g; 57 y >>= 1; 58 } 59 printf("%d", (f.b * a + f.a * b) % P); 60 } 61 return 0; 62 }