洛谷mNOIP模拟赛Day1-斐波那契

题目背景

大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg

题目描述

小 C 养了一些很可爱的兔子。 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行 繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子。我们假定, 在整个过程中兔子不会出现任何意外。

小 C 把兔子按出生顺序,把兔子们从 1 开始标号,并且小 C 的兔子都是 1 号兔子和 1 号兔子的后代。如果某两对兔子是同时出生的,那么小 C 会将父母标号更小的一对优先标 号。

如果我们把这种关系用图画下来,前六个月大概就是这样的:

其中,一个箭头 A → B 表示 A 是 B 的祖先,相同的颜色表示同一个月出生的兔子。

为了更细致地了解兔子们是如何繁衍的,小 C 找来了一些兔子,并且向你提出了 m 个 问题:她想知道关于每两对兔子 a_iai? 和 b_ibi? ,他们的最近公共祖先是谁。你能帮帮小 C 吗?

一对兔子的祖先是这对兔子以及他们父母(如果有的话)的祖先,而最近公共祖先是指 两对兔子所共有的祖先中,离他们的距离之和最近的一对兔子。比如,5 和 7 的最近公共祖 先是 2,1 和 2 的最近公共祖先是 1,6 和 6 的最近公共祖先是 6。

输入输出格式

输入格式:

从标准输入读入数据。 输入第一行,包含一个正整数 m。 输入接下来 m 行,每行包含 2 个正整数,表示 a_iai? 和 b_ibi? 。

输出格式:

输出到标准输出中。 输入一共 m 行,每行一个正整数,依次表示你对问题的答案。

输入输出样例

输入样例#1: 复制

5
1 1
2 3
5 7
7 13
4 12

输出样例#1: 复制

1
1
2
2
4 

说明

【数据范围与约定】 子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解 决一部分测试数据。 每个测试点的数据规模及特点如下表:



首先考虑70%的数据,

每天新出生的兔子数目一定是f[i],这个很容易计算得出

然后发现,这f[i]只兔子的父亲一定是1~f[i],于是模拟这个过程,做一遍LCA即可

再考虑100%的数据,

n达到int以上,无法模拟,

设s[i]=∑f[1~i],发现第s[i]+1只兔子父亲肯定是1,第s[i]+2只兔子父亲肯定是2,第s[i]+f[i+1]只兔子父亲一定是f[i+1]

于是有思路:二分s数组,使得s[i]+1<=a<=s[i]+f[i+1],这时候a的父亲就是a-s[i]

这样的话一开始a是大于s[i]的,减过之后就小于s[i]了,至少折半,效率至多是O(logn),感觉挺快的

对b也做一遍,记录他们的“祖先历程”,然后用两个指针找一下公共祖先就可以了

实际上我是处理到10^6的,如果小于10^6就直接做倍增了,这样可能快一些,不过事实证明是差不多的

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 #include<set>
  8 #include<queue>
  9 #include<vector>
 10 #define INF 0x7f7f7f7f
 11 #define pii pair<int,int>
 12 #define ll long long
 13 #define MAXN 1000005
 14 #define LOG 21
 15 using namespace std;
 16 ll read(){
 17     ll x=0,f=1;char ch=getchar();
 18     while(ch<‘0‘||ch>‘9‘){if(‘-‘==ch)f=-1;ch=getchar();}
 19     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 20     return x*f;
 21 }
 22 int fa[LOG][MAXN];
 23 ll M=1000000000005;
 24 ll dep[MAXN];
 25 ll f[MAXN]={1,1,1};
 26 ll s[MAXN]={1,2,3};
 27 vector<ll> v[2];
 28 int lca(int x,int y){
 29     if(dep[x]<dep[y]){
 30         swap(x,y);
 31     }
 32     for(int k=dep[x]-dep[y],p=0;k;p++,k>>=1){
 33         if(k&1){
 34             x=fa[p][x];
 35         }
 36     }
 37     if(x==y){
 38         return x;
 39     }
 40     for(int k=LOG-1;k>=0;k--){
 41         if(fa[k][x]!=fa[k][y]){
 42             x=fa[k][x],y=fa[k][y];
 43         }
 44     }
 45     return fa[0][x];
 46 }
 47 void work(ll a,int t){
 48     ll x=a;
 49     v[t].push_back(x);
 50     while(1){
 51         if(x<MAXN){
 52             break;
 53         }
 54         int L=0,R=60;
 55         while(R-L>1){
 56             int mid=(L+R)/2;
 57             if(s[mid]<x){
 58                 L=mid;
 59             }
 60             else{
 61                 R=mid;
 62             }
 63         }
 64         if(s[R]<x){
 65             x=x-s[R];
 66         }
 67         else{
 68             x=x-s[L];
 69         }
 70         v[t].push_back(x);
 71     }
 72 }
 73 void init(){
 74     fa[0][2]=fa[0][3]=1;
 75     dep[2]=dep[3]=1;
 76     int i=3,j=0;
 77     while(1){
 78         f[i]=f[i-1]+f[i-2];
 79         s[i]=s[i-1]+f[i];
 80         if(s[i]>M){
 81             break;
 82         }
 83         i++;
 84     }
 85     i=3;
 86     while(1){
 87         for(j=s[i-1]+1;j<=s[i]&&j<MAXN;j++){
 88             fa[0][j]=j-s[i-1];
 89             dep[j]=dep[j-s[i-1]]+1;
 90         }
 91         if(j>=MAXN){
 92             break;
 93         }
 94         i++;
 95     }
 96     for(int k=1;k<LOG;k++){
 97         for(int i=1;i<MAXN;i++){
 98             fa[k][i]=fa[k-1][fa[k-1][i]];
 99         }
100     }
101 }
102 void solve(){
103     int T=read();
104     while(T--){
105         ll a=read(),b=read();
106         if(a==b){
107             printf("%lld\n",a);
108             continue;
109         }
110         if(a<MAXN&&b<MAXN){
111             printf("%d\n",lca(a,b));
112         }
113         else{
114             v[0].clear(),v[1].clear();
115             work(a,0);
116             work(b,1);
117             int i=0,j=0,ok=0;
118             while(i<v[0].size()&&j<v[1].size()){
119                 if(v[0][i]==v[1][j]){
120                     printf("%lld\n",v[1][j]);
121                     ok=1;break;
122                 }
123                 if(v[0][i]>v[1][j]){
124                     i++;
125                 }
126                 else{
127                     j++;
128                 }
129             }
130             if(!ok){
131                 a=v[0][v[0].size()-1],b=v[1][v[1].size()-1];
132                  printf("%d\n",lca(a,b));
133             }
134         }
135     }
136 }
137 int main()
138 {
139 //    freopen("data.in","r",stdin);
140     init();
141     solve();
142     return 0;
143 }
时间: 2024-11-04 01:25:13

洛谷mNOIP模拟赛Day1-斐波那契的相关文章

【洛谷mNOIP模拟赛Day1】T1 斐波那契

题目传送门:https://www.luogu.org/problemnew/show/P3938 这题出得特别吼啊~~ 通过打表或者大胆猜想斐波那契数列的一些性质,我们不难发现对于一只兔子$x$,其父亲必为$x-Fk$($F$为斐波那契数列,且$F_{k}$为不大于$x$的最大数字),举个例子:$7-5=2$,$11-8=3$,对于点$x$和点$y$,我们分别求出其所有直系祖宗,然后扫一遍即可. 由于斐波那契数列为指数级增长,故向上跳的复杂度为一个$log$级别,时间复杂度为$O(m*log(

洛谷mNOIP模拟赛Day2-入阵曲

题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 丹青千秋酿,一醉解愁肠. 无悔少年枉,只愿壮志狂. 题目描述 小 F 很喜欢数学,但是到了高中以后数学总是考不好. 有一天,他在数学课上发起了呆:他想起了过去的一年.一年前,当他初识算法竞赛的 时候,觉得整个世界都焕然一新.这世界上怎么会有这么多奇妙的东西?曾经自己觉得难以 解决的问题,被一个又一个算法轻松解决. 小 F 当时暗自觉得,与自己的幼稚相比起来,还有好多要学习的呢. 一年过

洛谷mNOIP模拟赛Day1-分组

传送门 首先是贪心的思路 从后向前选,能多选就多选, 理由:数字越少肯定越优,同时间隔尽量向前推,字典序尽量小 对于K==1,枚举1~512直接判断 对于K==2,需要用镜像并查集,来刻画"敌对关系",如果a和b产生矛盾,就把a和b的镜像(b')连接 ,b和a'连接,然后判断自己是不是和自己的镜像连接了 打上时间戳避免清零卡常 1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4

洛谷mNOIP模拟赛Day1-数颜色

传送门 题目大意: 给定一个序列,维护每个数字在[L,R]出现的次数以及交换a[x]和a[x+1]的操作 一开始想的分桶法,感觉复杂度还可以吧,常数有点大,于是死得很惨(65分) 1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<

洛谷mNOIP模拟赛Day2-将军令

题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 历史/落在/赢家/之手 至少/我们/拥有/传说 谁说/败者/无法/不朽 拳头/只能/让人/低头 念头/却能/让人/抬头 抬头/去看/去爱/去追 你心中的梦 题目描述 又想起了四月. 如果不是省选,大家大概不会这么轻易地分道扬镳吧? 只见一个又一个昔日的队友离开了机房. 凭君莫话封侯事,一将功成万骨枯. 梦里,小 F 成了一个给将军送密信的信使. 现在,有两封关乎国家生死的密信需要送到前

[NOIP1997] P2626 斐波那契数列(升级版)

题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数). 题目描述 请你求出第n个斐波那契数列的数mod(或%)2^31之后的值.并把它分解质因数. 输入输出格式 输入格式: n 输出格式: 把第n个斐波那契数列的数分解质因数. 输入输出样例 输入样例#1: 5 输出样例#1: 5=5 输入样例#2: 6 输出样例#2: 8=2*2*2 说明 n<=48 97年的陈

【2017.11.2】洛谷 mNOIP 比赛 | T1 斐波那契【找规律】

Day 1 T1  斐波那契 找规律. 我们发现,兔子的编号减去斐波那契数列中第一个比它小的数之后就可以得到它的父亲.一直找减找减找减...就ok了. 题解(%%%dalao's 代码)

斐波那契数列的通项公式x+洛谷P2626x

#include<cstdio> #include<iostream> #include<cmath> using namespace std; int main() { int n; scanf("%d",&n); n--; double q=sqrt(5.0); int ans; ans=((pow((1+q)/2.0,n)/q-(pow((1-q)/2.0,n)/n))); cout<<ans<<endl; re

洛谷1349 广义斐波那契数列 【矩阵乘法】

洛谷1349 广义斐波那契数列 题目描述 广义的斐波那契数列是指形如an=p*an-1+q*an-2的数列.今给定数列的两系数p和q,以及数列的最前两项a1和a2,另给出两个整数n和m,试求数列的第n项an除以m的余数. 输入输出格式 输入格式: 输入包含一行6个整数.依次是p,q,a1,a2,n,m,其中在p,q,a1,a2整数范围内,n和m在长整数范围内. 输出格式: 输出包含一行一个整数,即an除以m的余数. 输入输出样例 输入样例#1: 1 1 1 1 10 7 输出样例#1: 6 说明