【洛谷3938】斐波那契

题目略

乍一看还以为是道LCA题,再一看数据范围,哦,数学题。。。

本来这题后三个点我是过不了的

开O2后AC

这题。。。。看眼数据范围就知道是数学题了(掩面

手动列一下各点的爹:

1 2 3 4 5 6 7 8 9 10 11 12 13

1 1 1 1 2 1 2 3 1 2 3 4 5

你会发现,就是个斐波那契。。。。。。

然后,因为fib是指数级增长的,所以打一下fib小于1e12的前缀和的表:

ll biao[59]={0,3,4,6,9,14,22,35,56,90,145,234,378,611,988,1598,2585,4182,6766,10947,17712,28658,46369,75026,121394,196419,317812,514230,832041,1346270,2178310,3524579,5702888,9227466,14930353,24157818,39088170,63245987,102334156,165580142,267914297,433494438,701408734,1134903171,1836311904,2971215074,4807526977,7778742050,12586269026,20365011075,32951280100,53316291174,86267571273,139583862446,225851433718,365435296163,591286729880,956722026042,1548008755921};

然后查找的时候只要二分:biao[mid]<=a<biao[mid+1]就可以了,复杂度一个log

后面的话用set维护链,爬链查找就可以了

注意要及时退出,并且清空set

 

附代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<set>
 4 #define ll long long
 5 using namespace std;
 6 template<typename T>
 7 inline void read(T &x){
 8   char ch;while((ch=getchar()),(ch>'9'||ch<'0'));
 9   x=ch-'0';while((ch=getchar()),(ch>='0'&&ch<='9')) x=x*10+ch-'0';
10 }
11 int m;
12 ll biao[59]={0,3,4,6,9,14,22,35,56,90,145,234,378,611,988,1598,2585,4182,6766,10947,17712,28658,46369,75026,121394,196419,317812,514230,832041,1346270,2178310,3524579,5702888,9227466,14930353,24157818,39088170,63245987,102334156,165580142,267914297,433494438,701408734,1134903171,1836311904,2971215074,4807526977,7778742050,12586269026,20365011075,32951280100,53316291174,86267571273,139583862446,225851433718,365435296163,591286729880,956722026042,1548008755921};
13 inline ll find(ll a){
14     if(a==1||a==2||a==3||a==4) return 1;
15     int l=0,r=58,mid;
16     while(l-r){
17         mid=l+((r-l)>>1);
18         if(a>=biao[mid]&&a<biao[mid+1]){return a-biao[mid]+1;}
19         if(a>biao[mid]) l=mid;
20         if(a<biao[mid]) r=mid;
21     }
22 }
23 set<ll> t;
24 int main(){
25     //freopen("in","r",stdin);
26     //freopen("out","w",stdout);
27     read(m);
28     register int i;
29     register ll a,b;
30     for(i=1;i<=m;++i){
31         read(a),read(b);
32         t.insert(a);
33         while(true){a=find(a),t.insert(a);if(a==1)break;}
34         if(t.count(b)){printf("%lld
",b),t.clear();continue;}
35         while(true){
36             b=find(b);
37             if(t.count(b)){printf("%lld
",b);break;}
38         }
39         t.clear();
40     }
41     return 0;
42 }
原文地址:https://www.cnblogs.com/lovely-lazy-tag-zly/p/7839193.html