题目大意
一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房M开始爬到蜂房N,M<N,有多少种爬行路线?M,N<=1000
题解
看到M,N<=1000,我们不能寻求通项解。我们从动规的角度看,令f(i)为从1到达编号为i的蜂房爬行路线总数,则f(i)=f(i-1)+f(i-2)。这就是斐波那契数的定义呀!求f(n-m)即可。注意斐波那契数很大,要用到高精度。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_LEN = 1001, BASE = 10000, CARRY = 4; struct BigInt { private: int A[MAX_LEN]; int Len; public: BigInt() { memset(A, 0, sizeof(A)); Len = 0; } BigInt& operator += (const BigInt& a) { for (int i = 0; i <= max(Len, a.Len); i++) { A[i] += a.A[i]; A[i + 1] += A[i] / BASE; A[i] %= BASE; } if (A[Len + 1]) Len++; return *this; } BigInt& operator = (const BigInt& a) { memcpy(A, a.A, sizeof(A)); Len = a.Len; return *this; } BigInt& operator = (int x) { memset(A, 0, sizeof(A)); Len = 0; while (x) { A[Len++] = x%BASE; x /= BASE; } while (Len > 0 && A[Len] == 0) Len--; return *this; } BigInt operator +(const BigInt& a) { BigInt ans = *this; return ans += a; } void Print() { printf("%d", A[Len]); for (int i = Len - 1; i >= 0; i--) printf("%0*d", CARRY, A[i]); } }; BigInt& GetF(int n) { static BigInt F[3]; F[0] = 1; F[1] = 1; for (int i = 2; i <= n; i++) F[i % 3] = F[(i - 1) % 3] + F[(i - 2) % 3]; return F[n % 3]; } int main() { int n, m; scanf("%d%d", &m, &n); GetF(n - m).Print(); return 0; }