链接:https://ac.nowcoder.com/acm/contest/71/C
来源:牛客网
题目描述
小W在计算一个数列{An},其中A1=1,A2=2,An+2=An+1+An。尽管他计算非常精准,但很快他就弄混了自己的草稿纸,他找出了一些他计算的结果,但他忘记了这些都是数列中的第几项。
输入描述:
每行包括数列中的一项Ak(k<=100000)。
总行数T<=30。
输出描述:
对于每一项Ak,输出一行包括一个正整数k表示输入中数是数列的第几项。
示例1
输入
2
3
5
8
13
输出
2
3
4
5
6
思路:
因为斐波拉契数列后面都是大数,没有办法记录实际的值
一个巧妙的办法是选择几个质数取模,用得到的几个余数来表示一个数的值
没有两个项的余数数组完全一样
题目数据范围1e5,因此预处理前1e5个数取模的余数数组
然后题目的大数输入用字符串,模拟一下大数取余弄出余数数组
最后暴力查找第一个完全相同的项 的位置就行了
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define int long long
const int maxm=1e5+5;
int mod[5]={5170427,1000000007,1000000009,12255871,163227661};//用5个质数
int f[maxm][5];
void init(){
for(int i=0;i<2;i++){//第0项和第1项为1
for(int j=0;j<5;j++){
f[i][j]=1;
}
}
for(int i=2;i<maxm;i++){
for(int j=0;j<5;j++){
f[i][j]=(f[i-1][j]+f[i-2][j])%mod[j];
}
}
}
char s[maxm];
signed main(){
init();
while(scanf("%s",s)!=EOF){
int len=strlen(s);
int a[5]={0};//存放输入的数对于五个质数取模的值
for(int i=0;i<len;i++){//对五个质数取模
int t=s[i]-'0';
for(int j=0;j<5;j++){
a[j]=(a[j]*10+t)%mod[j];
}
}
for(int i=0;i<maxm;i++){
int ok=1;
for(int j=0;j<5;j++){
if(a[j]!=f[i][j]){
ok=0;
break;
}
}
if(ok){//如果ok说明找到了
printf("%lld\n",i);//输出答案
break;
}
}
}
return 0;
}