Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E. Excellent Engineers-单点更新、区间最值-线段树 G. Growling Gears I. Interesting Integers-类似斐波那契数列-递推思维题

先写这几道题,比赛的时候有事就只签了个到。

E. Excellent Engineers

传送门:

这个题的意思就是如果一个人的r1,r2,r3中的某一个比已存在的人中的小,就把这个人添加到名单中。

因为是3个变量,所以按其中一个变量进行sort排序,然后,剩下的两个变量,一个当位置pos,一个当值val,通过线段树的单点更新和区间最值操作,就可以把名单确定。

代码:

 1 //E-线段树
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<cstdlib>
 8 #include<queue>
 9 #include<stack>
10 using namespace std;
11 typedef long long ll;
12 const int inf=0x3f3f3f3f;
13 const double eps=1e-5;
14 const int maxn=1e5+10;
15 #define lson l,m,rt<<1
16 #define rson m+1,r,rt<<1|1
17 struct node
18 {
19     int x,y,z;
20     bool operator<(const node&a)const
21     {
22         return x<a.x;
23     }
24 }a[maxn];
25 int tree[maxn<<2];
26
27 void PushUp(int rt)
28 {
29     tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
30 }
31
32 void build(int l,int r,int rt)
33 {
34     if(l==r)
35     {
36         tree[rt]=inf;
37         return ;
38     }
39     int m=(l+r)>>1;
40     build(lson);
41     build(rson);
42     PushUp(rt);
43 }
44 //单点更新
45 void update(int pos,int val,int l,int r,int rt)
46 {
47     if(l==r)
48     {
49         tree[rt]=val;
50         return ;
51     }
52     int m=(l+r)>>1;
53     if(pos<=m)update(pos,val,lson);
54     else update(pos,val,rson);
55     PushUp(rt);
56 }
57
58 //区间最值
59 int query(int L,int R,int l,int r,int rt)
60 {
61     if(L<=l&&r<=R)
62     {
63         return tree[rt];
64     }
65     int m=(l+r)>>1;
66     int ret=inf;
67     if(L<=m)ret=min(ret,query(L,R,lson));
68     if(R> m)ret=min(ret,query(L,R,rson));
69     return ret;
70 }
71
72
73 int main()
74 {
75     int t,n;
76     scanf("%d",&t);
77     while(t--)
78     {
79         scanf("%d",&n);
80         build(1,n,1);
81         for(int i=0;i<n;i++)
82             scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
83         sort(a,a+n);
84         int ans=0;
85         for(int i=0;i<n;i++)
86         {
87             if(a[i].y!=1)
88             {
89                 int cnt=query(1,a[i].y-1,1,n,1);
90                 if(cnt<a[i].z)continue;
91             }
92             ans++;
93             update(a[i].y,a[i].z,1,n,1);
94         }
95         printf("%d\n",ans);
96     }
97     return 0;
98 }

G. Growling Gears

传送门:

此题为签到题,直接中学的数学知识点,一元二次方程的顶点公式(-b/2*a,(4*a*c-b*b)/4*a);直接就可以得到结果。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<queue>
 7 #include<map>
 8 #include<algorithm>
 9 using namespace std;
10 typedef long long ll;
11 const int maxn=1e5+10;
12 int main(){
13     int t;scanf("%d",&t);
14     while(t--){
15         int n;scanf("%d",&n);
16         int a,b,c;
17         ll maxx=-1;int ans;
18         for(int i=1;i<=n;i++){
19             scanf("%d%d%d",&a,&b,&c);
20             ll cnt=(4*a*c*(-1)-b*b)/(4*a*(-1));
21             if(maxx<=cnt){
22                 maxx=cnt;
23                 ans=i;
24             }
25         }
26         printf("%d\n",ans);
27     }
28     return 0;
29 }

I. Interesting Integers

传送门:

应该是叫思维题吧,反正敲一下脑壳才知道自己哪里写错了。要敢于暴力。

这个题的题意就是给你一个数,让你逆推出递推的最开始的两个数(假设一开始的两个数为x和y),而且要求x<=y。

通过找规律可以发现,这个题就是求解a*x+b*y=k这个方程的x和y的值,并且要x和y为最小满足条件的解。可以找规律出一个公式fi[i]*x+(fi[i-1]+fi[i])*y=n。因为不知道n具体是在第几步推出来的,所以for循环跑一遍预处理出来的斐波那契数列(存到fi数组中),最多不超过50个数,否则会爆1e9。

因为是求解a*x+b*y=k这个方程的x和y的值,并且要x和y为最小满足条件的解,当时脑子一热就说,这不是扩展欧几里得吗,然后突然发现,斐波那契数列相邻两个数是互质的,他们的exgcd为1,并没有什么用,打扰了,所以还是老老实实去写暴力。

通过该方程,可以大体确定y的范围,y=1;y<=cnt+1,因为要求在满足a<=b的条件下的最小值,所以斐波那契数列中的数作为两个数的系数,只有系数尽可能大,这两个数才会尽可能小,所以斐波那契数列的遍历从大到小遍历,因为要求y尽量小的前提下x小且x<=y,所以从小到大遍历y,找到第一个满足条件:x<=y的就是结果。如果都是从大到小或者从小到大遍历或者怎么遍历,会超时,所以找到结果直接输出就可以了。

自己写的时候,2和4的结果输不出来,然后特判2和4水过去了,仔细想了一下,发现是斐波那契数列初始值设错了,把0给忘了,然后改了之后就过了。简直是智障,智障写了好久的智障题。。。

代码:

 1 //I-斐波那契数列打表
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<map>
 9 #include<algorithm>
10 using namespace std;
11 typedef long long ll;
12 const int maxn=1e5+10;
13 const int inf=0x3f3f3f3f;
14 int fi[50];
15 void fibonacci()
16 {
17     fi[0]=0,fi[1]=1;fi[2]=1;
18     for(int i=3;i<=45;i++)
19         fi[i]=fi[i-1]+fi[i-2];
20 }
21 int main()
22 {
23     int t,n;
24     fibonacci();
25     scanf("%d",&t);
26     while(t--)
27     {
28         scanf("%d",&n);
29         {
30             int flag=0;
31             for(int i=45;i>=0;i--)
32             {
33                 int a=fi[i],b=fi[i-1]+fi[i];
34                 int cnt=n/a;
35                 for(int y=1;y<=cnt+1;y++)
36                 {
37                     if((n-b*y)%a==0&&(n-b*y)>0)
38                     {
39                         int x=(n-b*y)/a;
40                         if(x<=y&&x!=0)
41                         {
42                             flag=1;
43                             printf("%d %d\n",x,y);
44                             break;
45                         }
46                     }
47                     if(flag==1)break;
48                 }
49                 if(flag==1)break;
50             }
51         }
52     }
53     return 0;
54 }

感谢思力酱,嘲笑我的智障行为并且锤了我的脑壳,让我机灵一下发现是初始值设错了,思力酱是真的严格呢。

就先这样吧,其他题等补了再写题解。

原文地址:https://www.cnblogs.com/ZERO-/p/9297446.html

时间: 2024-12-26 23:57:08

Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E. Excellent Engineers-单点更新、区间最值-线段树 G. Growling Gears I. Interesting Integers-类似斐波那契数列-递推思维题的相关文章

BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 A. Choosing Ice Cream-gcd B. Failing Components-最短路Dijkstra F. Runway Planning

开始水一波博客 题目链接: A. Choosing Ice Cream 传送门 题意就是n个冰淇淋,骰子有k个面,问你是否能在公平的概率下转几次骰子能确定买哪个冰淇淋. 举个例子,假设我只有一个冰淇淋,我不用转骰子直接就会买这个,所以转骰子的次数是0,如果我有4个冰淇淋,2个骰子面,我可以先把冰淇淋abcd分成两部分,ab一组,cd一组,这是等概率的,我先转一次骰子确定是选ab组还是cd组,然后再转一次就可以确定买哪个了.如果我有6个冰淇淋,12个面,我可以每一种冰淇淋贴2个面,转一次就可以确定

斐波那契数列——摘自搜狗百科

1数列公式 递推公式 斐波那契数列:0.1.1.2.3.5.8.13.21.34.55.89.144... 如果设F(n)为该数列的第n项(n∈N*),那么这句话可以写成如下形式: F(0) = 0,F(1)=F(2)=1,F(n)=F(n-1)+F(n-2) (n≥3) 通项公式 通项公式的推导方法一:利用特征方程 线性递推数列的特征方程为: X^2=X+1 解得 X1=(1+√5)/2, X2=(1-√5)/2. 斐波拉契数列则F(n)=C1*X1^n + C2*X2^n ∵F(1)=F(2

斐波那契数列实例讲解以及C++实现

斐波那契数列,又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在现代物理.准晶体结构.化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963起出版了以<斐波纳契数列季刊>为名的一份数学杂志,用于专门刊载这方面的研究成果. 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34,

“斐波那契数列”衍生题

一.斐波那契数列 斐波那契数列是这样的一组数列:1.1.2.3.5.8.13.21.34.……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)即大于2的部分是由前两个相加获得. 若要求第 N 个数的值,我们可以用递归也可以通过迭代的方式求解 1.递归 def fibonacci(n): if n == 1 or n == 2: return 1 return fibonacci(n - 1) + fibona

【poj3070】矩阵乘法求斐波那契数列

[题目描述] 我们知道斐波那契数列0 1 1 2 3 5 8 13…… 数列中的第i位为第i-1位和第i-2位的和(规定第0位为0,第一位为1). 求斐波那契数列中的第n位mod 10000的值. [分析] 这是我们熟悉的斐波那契数列,原来呢我们是递推求值的嘛,当然这是最水的想法~~可是!这里的n很大诶,有10^9,for一遍肯定是不可以的咯. 于是,我学会了用矩阵乘法求斐波那契数列(貌似是很经典的). 作为初学者的我觉得十分神奇!! 好,我们来看: 我们每次存两个数f[i-1]和f[i-2],

矩阵乘法&amp;&amp;矩阵快速幂&amp;&amp;最基本的矩阵模型——斐波那契数列

矩阵,一个神奇又令人崩溃的东西,常常用来优化序列递推 在百度百科中,矩阵的定义: 在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合 ,最早来自于方程组的系数及常数所构成的方阵.这一概念由19世纪英国数学家凯利首先提出. 好,很高深对吧.那我们就更加直接地理解一下矩阵的实质:二维数组 好了这个SB都会,就不解释了 同二维数组一样,矩阵是一个'纵横排列的二维数据表格',它一般是一个n*m的二维数组,其中n*m表示它有n行m列 每一位上的数可以用下标i,j来表示,形如这样一个矩阵:

树上三角形(斐波那契数列神奇应用)

树上三角形(斐波那契数列神奇应用) Description给定一个大小为 n 的有点权树,需要支持两个操作.0:询问(u,v),能否在 u 到 v 的简单路径上取三个点,使这三个点的点权作为边长可以构成一个三角形.1:修改某个点的点权. Input第一行两个整数 n,q 表示树的点数和操作数.第二行 n 个整数表示 n 个点的初始的点权.接下来 n-1 行,每行两个整数 a,b,表示 a 是 b 的父亲.接下来 q 行,每行三个整数 op,a,b:若 op=0,则表示询问(a,b).若 op=1

递归思想之---斐波拉契数列

斐波那契数列中的递归思想 ??如果上述的分析都明白了,那就说明你已掌握了递归,但为了加深对递归的理解,我们再来看一个思考题(来自程序员的数学思考题),题目是这样的,假如动物中有一种特殊的种类,它出生2天后就开始以每天1只的速度繁殖后代.假设第1天,有1只这样的动物(该动物刚出生,从第3天开始繁殖后代).那么到第11天,共有多少只呢? 我们先来按一般顺序思考,先不要考虑第11天,先从第1天开始,看能不能找出规律: [第1天]只有1只动物 [第2天]只有1只动物,还没有繁殖后代,总量为1 [第3天]

斐波那契数列问题的两种解决方法

斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........ 这个数列从第3项开始,每一项都等于前两项之和. 简单来说,斐波那契数列可以用下面这个公式来表示. { 0 ,n=0 f(n)={ 1 ,n=1 { f(n-1)+f(n-2) ,n>1 关于斐波那契数列衍生的算法题层出不穷,比如青蛙跳台阶问题等(