斐波那契数列 兔子

题目描述
在一个班级里面有 m mm 个学生,每个人的学号是 0 00 到 m − 1 m-1m−1 的 m mm 个数字。现在老师出了一道谜题,如果所有人都答出来,那么就只有谜底表示的人需要做作业,否则所有人都要做作业(显然大家都会积极的找出谜底,因为谁都不想写作业),谜题如下: 假设有一对兔子,长两个月它们就算长大成年了。然后以后每个月都会生出 1 11 对兔子,生下来的兔子也都是长两个月就算成年,然后每个月也都会生出 1 11 对兔子了。这里假设兔子不会死,每次都是只生 1 11 对兔子。 第一个月只有一对刚出生的小兔子(标号为 0 00 )。每对出生的兔子按照按照出生顺序 0 00 到 m − 1 m-1m−1 循环标号,前 n nn 个月内出生的最后一对兔子的标号就是需要做作业的人的学号。你能找出谜底吗?

输入描述:
有 T TT 组输入,每组数据输入一行。( 1 ≤ T ≤ 50 ) (1\le T \le 50)(1≤T≤50)
每行两个整数 n , m n,mn,m 。( 1 ≤ m ≤ 500 , 1 ≤ n ≤ 1000 ) (1\le m \le 500,1\le n \le 1000)(1≤m≤500,1≤n≤1000)
输出描述:
每组数据输出一行,
每行一个数字,做作业人的标号。

输入 输出
4
3 20
5 4
1 10
2 10 1
0
0
0
分析
这题很像 HDU-2018 母牛的故事 。

若把一对兔子看作一个点,那么题中的情况就如下图所示:
( f ( n ) f(n)f(n) 代表第 n nn 个月有几对兔子🐇)


我们很容易发现 f ( n ) f(n)f(n) 与斐波那契数列相当。
但如果直接斐波那契数列打表,最后才对 m mm 取模会WA。因此只需要每组询问都重新计算 f ff 数组的值就可以了。


最后才对 m mm 取模会WA的原因:斐波那契数列到后面会越来越大,当 n nn 的值很大时,f ( n ) f(n)f(n) 的值会非常大,因此会溢出,从而对结果产生影响。

代码
#include<cstdio>
using namespace std;
typedef long long ll;
const ll maxn=1e3+10;
const ll mod=1e9+7;

int T,n,m;
ll f[maxn]; //兔子的对数

void fib()
{
f[0]=f[1]=f[2]=1;
for(int i=3;i<maxn;i++)
f[i]=f[i-1]%m+f[i-2]%m;
}

int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
fib();
printf("%lld\n",(f[n]-1+m)%m); //问的是最后一个点的编号
}
return 0;
}

posted @ 2021-10-09 16:42  Night_Voyager-qaq  阅读(196)  评论(0编辑  收藏  举报
Live2D