斐波那契数列 兔子
题目描述
在一个班级里面有 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;
}