题目:
给出一个斐波那契数字的前缀,问第一个有这个前缀的数字在斐波那契数列中是第几个。
思路:
紫书提示:本题有一定效率要求。如果高精度代码比较慢,可能会超时。
利用滚动数组和竖式加法来模拟斐波那契相加的过程,在这个过程中每得出一个斐波那契数字就用字典树存一下。
PS:在滚动数组中存的斐波那契数字是逆序存储的。
代码:
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define MAX 1e9; #define FRE() freopen("in.txt","r",stdin) #define FRO() freopen("out.txt","w",stdout) using namespace std; typedef long long ll; const int maxn = 4000010; struct Node { int next[10]; int id; Node() { for(int i = 0; i<10; i++) { next[i] = -1; } id = -1; } }; Node trie[maxn]; int tot = 0; //Node root = trie[tot++]; int idx(char ch) {return ch-‘0‘;} void Insert(char* str, int id) {//字典树插入 // int u = 0; // for(int i = 0; i<strlen(str); i++) { // int v = idx(str[i]);//获取字符串当前位置的数字 // if(trie[u].next[v]==-1) { //如果这个位置是不存在的 // trie[u].next[v] = tot; // u = tot++; // } else { //如果这个位置是存在的 // u = trie[u].next[v]; // } // if(trie[u].id==-1) { // trie[u].id = id; // } // } int u = 0; for(int i = 0; i<strlen(str); i++){ int v = idx(str[i]); if(trie[u].next[v]==-1){//如果这个位置不存在 trie[u].next[v] = tot++; } u = trie[u].next[v];//结点往下走 if(trie[u].id==-1){//保存这个斐波那契数字的id trie[u].id = id; } } } int Query(char* str) { int u = 0; for(int i = 0; i<strlen(str); i++) { int v = idx(str[i]); if(trie[u].next[v]==-1) { //说明这个前缀不会出现 return -1; } u = trie[u].next[v]; } return trie[u].id; } int fib[2][maxn]; int main() { FRE(); int s=0,l=1; char f[55]; Insert("1",1); fib[1][0] = 1; fib[0][0] = 0; for(int i=2; i<100000; i++) { int a=i%2, b=(i+1)%2;//滚动数组,可以手动跑两组斐波那契数字的相加就可以理解了 for(int k=s; k<l; k++) { fib[a][k] = fib[a][k] + fib[b][k]; if(fib[a][k]>=10) { //这位相加可以进位时 fib[a][k+1]++;//下一位加一 fib[a][k] -= 10;//这一位减掉进位的10 if(k==l-1) { //最后一个进位让l加一 l++; } } } if(l-s>50) { //数组中是倒着存这个数的,l-1表示个位开始,s表示最高位 s++; } int cnt=0; for(int k=l-1; k>=s&&cnt<40; k--){//根据题目提示,只选取前40位即可 f[cnt++] = fib[a][k]+‘0‘; } // if(i==10) // printf("%s\n",f); Insert(f,i); memset(f,0,sizeof(f)); } //cout<<"GG"<<endl; char str[55]; int n; scanf("%d",&n); for(int i=0; i<n; i++){ scanf("%s",str); printf("Case #%d: ",i+1); int ans = Query(str); printf("%d\n",ans==-1 ? -1:ans-1); } return 0; }
原文地址:https://www.cnblogs.com/sykline/p/10285500.html
时间: 2024-10-11 06:51:45