斐波那契數列——兔子問題


斐波那契數列——兔子問題:

春天來了, 又到了交配的季節。一般而言, 一對兔子在出生一個月后(即出生后的第二個月)就
有了繁殖能力,此后一對兔子每個月能生出一對小兔子來。例如,若最開始有一對剛出生的兔子,
兔子的繁殖如下表所示:
經過月份 0 1 2 3 4 5 6 7
幼崽對數 1 0 1 1 2 3 5 8
成兔對數 0 1 1 2 3 5 8 13
總對數 1 1 2 3 5 8 13 21
現在,在原問題的基礎上假設每對兔子都會在產下第 m 對后代后死亡,其中 m 是一個確定的
數,問經過 n 個月后有多少對兔子。注意衰老的兔子在產下第 m 對兔子后立即死亡,不算入該月
總體對數統計,例如當 n = 10, m = 5 時,我們有:
經過月份 0 1 2 3 4 5 6 7 8 9 10
幼崽對數 1 0 1 1 2 3 5 7 12 18 29
1 歲成兔對數 0 1 0 1 1 2 3 5 7 12 18
2 歲成兔對數 0 0 1 0 1 1 2 3 5 7 12
3 歲成兔對數 0 0 0 1 0 1 1 2 3 5 7
4 歲成兔對數 0 0 0 0 1 0 1 1 2 3 5
5 歲成兔對數 0 0 0 0 0 1 0 1 1 2 3
總對數 1 1 2 3 5 8 12 19 30 47 74
注意答案可能非常大,所以請對 1000000007 取模。

斐波那契數列——兔子問題是經典的遞推題,但是如果考慮兔子會死的情況呢。

假設一只兔子產m代之后會死,也就是以

當現在還沒有到m+1代時,有:

\(dp[i]=dp[i-1]+dp[i-2]\)

正好在m+1月時,需要減去第1個月的那一對。

而在\(>=m+2\)月時,

\(dp[i] = dp[i - 1] + dp[i - 2] - dp[i - m - 2]\);

可是為什么是\(-dp[i-m-2]\),由於我們記\(dp[i]\)為i時刻還活着的兔子。

而當i為活着的右區間時,\(i-(m+1)\)是左區間。

所以求前綴和的時候要減\(i-(m+1)-1\)

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9+7;
int dp[1001000] = {1, 1, 2};
int s[100100];
signed main()
{
	int n, m, ans = 0;
	int T;
//	freopen("B.in", "r", stdin);
//	freopen("B.out", "w", stdout);
	scanf("%lld", &T);
	while (T--)
	{
		int ans = 0, temp = 0;
		scanf("%lld%lld", &n, &m);
		m = min(m, n);
		for (int i = 2; i <= n; i++)
		{
			if (i <= m)
			dp[i] = ( (dp[i - 1] % mod) + (dp[i - 2] % mod) + mod) % mod;
			else if (i == m + 1)
			dp[i] = ( (dp[i - 1] % mod) + (dp[i - 2] % mod) - (dp[1] % mod) + mod ) % mod;
			else
			dp[i] = ( (dp[i - 1] % mod) + (dp[i - 2] % mod) - (dp[i - m - 2] % mod) + mod) % mod ;
		}
		printf("%lld\n", dp[n] % mod);
	}
}
/*
2
5 10
8 5
*/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM