很高兴给大家出题,本次难度低于上一场,新生的六个题都可以直接裸递归式或者裸递推式解决,对于老生的汉诺塔3,需要找出一般式,后两题分别为裸ST算法(或线段树)/线性DP。

正确的难度顺序为

  1. 种花
  2. 角谷定律
  3. 猴子和椰子
  4. 汉诺塔1
  5. 汉诺塔2
  6. 整数划分
  7. 跳台阶
  8. 汉诺塔3
  9. 夏目友人帐(一)
  10. 夏目友人帐(二)

一、种花

本题很容易能推出递推式或者一般式,对于第一快地,有3种种植方法,对于后面的每一快地有不同于前一块地的两种种植方法。

  • a1 = 3;
  • an = 2*(an-1);

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int a[25];
 5
 6 void init(){
 7     a[1] = 3;
 8     for(int i = 2; i <= 20; i++){
 9         a[i] = a[i-1]*2;
10     }
11 }
12
13 int main(){
14     freopen("test.out","w",stdout);
15     int n;
16     init();
17     while(cin>>n){
18         cout << a[n] << endl;
19     }
20     return 0;
21 }

二、角谷定律

本题按照给出的式子操作即可,用另外一个变量记录操作次数。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int cnt = 0;
 5 void fun(long long n){
 6     if(n == 1)
 7         return ;
 8     if(n&1)
 9         cnt++,fun(3*n+1);
10     else
11         cnt++,fun(n/2);
12 }
13
14 int main(){
15     int n;
16     freopen("test.in","r",stdin);
17     freopen("test.out","w",stdout);
18     while(cin>>n){
19         cnt = 0;
20         fun(n);
21         cout << cnt << endl;
22     }
23     return 0;
24 }

三、猴子和椰子

可能你们也在其他地方看见过本题,设初始椰子为A,最后一次分给每个人的椰子为n,很容易推得一个A关于n得常数式子,因为要保证能够按照题目分下去,所以要保证每次分椰子都为正整数,已得答案为15621(5^6 - 4)。算是个小学数学题。

输出15621即可。

四、汉诺塔1

这是一个汉诺塔的基本变式,其实用汉诺塔的思想去想也不难,要移动n根木根从A至C,可划分为下面几个步骤。

  • 先移动n-1根木根到C
  • 移动第n根木棍到B
  • 移动C上的n-1根木棍到A
  • 移动B上的第n根木棍到C
  • 移动A上的n-1根木棍到C

至此,完成这个汉诺塔的移动,我们把移动n根木棍从A到C计为F(n)。

则F(n) = F(n-1) + 1 + F(n-1) + 1 + F(n-1) = 3*F(n-1) + 2;且F(1) = 2;

按照这个步骤写出递归函数即可。代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 long long fun(int n){
 5     if(n == 1)
 6         return 2;
 7     return 3*fun(n-1)+2;
 8 }
 9
10 int main(){
11     freopen("test.in","r",stdin);
12     freopen("test.out","w",stdout);
13     int n;
14     while(cin>>n){
15         cout << fun(n) << endl;
16     }
17     return 0;
18 }

五、汉诺塔2

在汉诺塔1的基础上多了可以把最长的木棍放在最上面,还是按照上面的步骤,移动n根木棍从A到C可划分为

  • 移动n-1根木棍从A到B
  • 移动第n根木棍到B上
  • 移动第n根木棍到C上
  • 移动n-1根木棍从B到C

至此,完成汉诺塔的移动,我们把移动n根木根从A到C计为F(n),移动n根木棍到邻柱子计为T(n),关于T(n)的公式这里就不推了,演变方式一样。

所以有F(n) = T(n-1)+1+1+T(n-1) = 2*T(n-1)+2;且F(1) = 2;

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int fc(int n){
 5     if(n == 1)
 6         return 1;
 7     return 3*fc(n-1)+1;
 8 }
 9
10 int fun(int n){
11     if(n == 1)
12         return 2;
13     return 2*fc(n-1)+2;
14 }
15
16 int main(){
17     freopen("test.in","r",stdin);
18     freopen("test.out","w",stdout);
19     int n;
20     while(cin>>n){
21         cout << fun(n) << endl;
22     }
23     return 0;
24 }

六、整数划分

其实这个题题面以及给出了一点提示,把n分成m个正整数的和,要直接求n的划分个数比较难,但是我们可以求n-1、n-2,,,的划分,设n = ΣDi,且max(Di) <= k,

即Di为n的一种划分方案,最大数字不超过k,把它计为F(n,k),那么本题也就是求F(n,n);根据 n,k的不同大小关系,可得下列递归式

  • F(n, k) = 1; (n =1 or k = 1)
  • F(n, k) = F(n, n); (n < k)
  • F(n, k) = F(n, k-1) + 1; (n = k)
  • F(n, k) = F(n-k, k) + F(n, k-1); (n > k)

所以可以写出代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int fun(int n,int m){
 5     if(n == 1 || m == 1)
 6         return 1;
 7     else if(n < m)
 8         return fun(n,n);
 9     else if(n == m)
10         return fun(n,n-1)+1;
11     else if(n > m)
12         return fun(n,m-1)+fun(n-m,m);
13 }
14
15 int main(){
16     freopen("test.in","r",stdin);
17     freopen("test.out","w",stdout);
18     int n;
19     while(cin>>n){
20         cout << fun(n,n) << endl;
21     }
22     cerr << clock() << endl;
23     return 0;
24 }

七、跳台阶

其实很容易推出对于n阶台阶的方案有

F(n) = Σ(F(n-Pi)); (P1 = 1,Pi = 质数集合)

边界条件F(1) = F(0) = 1;

所以代码显而易见了,其实本题还想卡一下数据范围,因为34好像就会爆int,还是算了,就只给你们弄到30,而且本题开了4s,其实我STD只跑了1.7s,奈何只能取整,干脆就4s得了。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int prime[1100],primesize,phi[1100];
 5 bool isprime[1100];
 6
 7 int n;
 8
 9 void getlist(int listsize){
10     memset(isprime,1,sizeof(isprime));
11     isprime[1]=false;
12     for(int i=2;i<=listsize;i++)
13     {
14         if(isprime[i])prime[++primesize]=i;
15          for(int j=1;j<=primesize&&i*prime[j]<=listsize;j++)
16          {
17             isprime[i*prime[j]]=false;
18             if(i%prime[j]==0)break;
19         }
20     }
21     prime[0] = 1;
22 }
23
24 int fun(int n){
25     int sum = 0;
26     if(n == 1 || n == 0)
27         return 1;
28     for(int i = 0; i <= primesize; i++){
29         if(n < prime[i])
30             break;
31         sum += fun(n-prime[i]);
32     }
33     return sum;
34 }
35
36 int main(){
37     freopen("test.in","r",stdin);
38     freopen("test.out","w",stdout);
39     ios_base::sync_with_stdio(false);
40     getlist(100);
41     int n;
42     while(cin>>n){
43         cout << fun(n) << endl;
44     }
45     cerr << clock() <<endl;
46 }

八、汉诺塔3

四柱汉诺塔问题,我都懒得写如何推了,易得下面递归式

F(n) = min(2*F(n-r)+2r-1),1 <= r <= n;

但是直接用上面式子写递归式肯定会时间爆炸,不信你试试。

最大n不超过100,所以其实你先递推出任意一项就可以了= =,这样的话预处理时间为O(n2),查询时间为O(1)。为了你们好= =所以我没有卡这种算法。

但其实也可以得出一般式,根据Frame-Stewart算法可得出当r = floor((sqrt(8*n+1)-1)/2)时,有最小值,且最小值F(n) = (n - (r2-r+2)/2)*2r+1;

即可以在O(1)时间内得出任意n根木棍需要的最小转移次数。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int a[105] = {0};
 5
 6 int init(){
 7     fill(a,a+101,0x3f3f3f3f);
 8     a[0] = 0,a[1] = 1,a[2] = 3;
 9     for(int i = 3; i <= 100; i++){
10         for(int j = 1; j < 32; j++){
11             temp = 2*a[j]+pow(2LL,(long long)j)-1;
12             a[i] = min(a[i],temp);
13         }
14     }
15 }
16
17 int main(){
18     freopen("test.in","r",stdin);
19     freopen("test.out","w",stdout);
20     int n;
21     while(cin>>n){
22         int r = floor((sqrt(8*n+1)-1.0)/2.0);
23         int ans = (n-(r*r-r+2)/2.0)*pow(2.0,r)+1;
24         cout << ans << endl;
25     }
26     cerr << clock() << endl;
27     return 0;
28 }

九、夏目友人帐(一)

经典RMQ问题,ST/线段树都可以。

本来想卡线段树做法,想了一下不卡算了= =。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 //线段树
 5 #define lson l,m,p<<1
 6 #define rson m+1,r,p<<1|1
 7 #define Max(a,b) (a<b?b:a)
 8 #define Min(a,b) (a<b?a:b)
 9 #define INF 999999999
10
11 int N,M;
12 int MaxP[100000*4+10];
13 int maxT;
14 void Update(int val,int K,int l,int r,int p){
15     int m=(l+r)>>1;
16     if(l==r){
17         MaxP[p]=val;
18         return;
19     }
20     if(K<=m)
21         Update(val,K,lson);
22     else
23         Update(val,K,rson);
24     MaxP[p]=Max(MaxP[p<<1],MaxP[p<<1|1]);
25 }
26 void Query(int L,int R,int l,int r,int p){
27     int m=(l+r)>>1;
28     if(L<=l&&r<=R){
29         maxT=Max(maxT,MaxP[p]);
30         return;
31     }
32     if(L<=m)
33         Query(L,R,lson);
34     if(R>=m+1)
35         Query(L,R,rson);
36 }
37 int main(){
38     freopen("test2.in","r",stdin);
39     freopen("test2.out","w",stdout);
40     int i,val,a,b;
41     scanf("%d %d",&N,&M);
42     for(i=1;i<=N;i++){
43         scanf("%d",&val);
44         Update(val,i,1,N,1);
45     }
46     for(i=1;i<=M;i++){
47         scanf("%d %d",&a,&b);
48         maxT=0;
49         Query(a,b,1,N,1);
50         printf("%d\n",maxT);
51     }
52     cerr << clock() << endl;
53     return 0;
54 }
55
56 //ST算法
57 int N,M;
58 int A[500005];
59 int FMax[500005][27];
60
61 void Init(){
62     int i,j;
63     for(i=1;i<=N;i++)
64         FMax[i][0]=A[i];
65     for(i=1;(1<<i)<=N;i++){
66         for(j=1;j+(1<<i)-1<=N;j++){
67             FMax[j][i]=max(FMax[j][i-1],FMax[j+(1<<(i-1))][i-1]);
68         }
69     }
70 }
71
72 int Query(int l,int r){
73     int k=(int)(log(r-l+1)/log(2));
74     return max(FMax[l][k],FMax[r-(1<<k)+1][k]);
75 }
76
77 int main(){
78     freopen("test1.in","r",stdin);
79     freopen("test1.out","w",stdout);
80     int i,a,b;
81     scanf("%d %d",&N,&M);
82     for(i=1;i<=N;i++)
83         scanf("%d",&A[i]);
84     Init();
85     for(i=1;i<=M;i++){
86         scanf("%d %d",&a,&b);
87         printf("%d\n",Query(a,b));
88     }
89     cerr << clock() << endl;
90     return 0;
91 }

十、夏目友人帐(二)

这里就不说怎么推的了,到时候认真听我黑板上讲23333。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4
 5 const int N = 210;
 6 const int Q = 1010;
 7 int f[Q][N][N];
 8 int p[Q];
 9 int c[N][N];
10
11 int main(){
12     freopen("test3.in","r",stdin);
13     freopen("test3.out","w",stdout);
14     ios_base::sync_with_stdio(false);
15     cin.tie(0);
16     cout.tie(0);
17     int n,q;cin>>n>>q;
18     for(int i = 1; i <= n; i++){
19         for(int j = 1; j <= n; j++){
20             cin>>c[i][j];
21         }
22     }
23     for(int i = 1; i <= q; i++){
24         cin>>p[i];
25     }
26     memset(f,0x3f,sizeof(f));
27     int INF = f[0][0][0];
28     p[0] = 3;
29     f[0][1][2] = 0;
30     for(int i = 1; i <= q; i++){
31         for(int x = 1; x <= n; x++){
32             for(int y = 1; y <= n; y++){
33                 if(x != p[i] && y != p[i])
34                     f[i][x][y] = min(f[i][x][y],f[i-1][x][y]+c[p[i-1]][p[i]]);
35                 if(p[i] != y && p[i] != p[i-1])
36                     f[i][p[i-1]][y] = min(f[i][p[i-1]][y],f[i-1][x][y]+c[x][p[i]]);
37                 if(p[i] != x && p[i] != p[i-1])
38                     f[i][x][p[i-1]] = min(f[i][x][p[i-1]],f[i-1][x][y]+c[y][p[i]]);
39             }
40         }
41     }
42     int ans = INF;
43     for(int i = 1; i<= n; i++){
44         for(int j = 1; j<= n; j++){
45             ans = min(ans,f[q][i][j]);
46         }
47     }
48     cout << ans << endl;
49     cerr << clock() << endl;
50     return 0;
51 }


P.S. 其实很多题目都可以卡你们算法,不卡不卡,怕被打= =,后面给你们出卡常数233333

转载于:https://www.cnblogs.com/xenny/p/9971264.html

第二场周赛(递归递推个人Rank赛)——题解相关推荐

  1. 【考试题解】 递归递推

    T1:station 题目描述: 小 VHOS 带着 N 颗山楂球来到 A 班的阵地准备缩到位置上吃山楂球. 但是 A 班大佬们太强了,所以小 VHOS 每经过一个 A 班大佬身边, 他都需要交出他 ...

  2. 青少年软件编程(202209)(C语言)(枚举递归递推)等级考试(三级)试题及参考答案

    等级标准 掌握算法以及算法性能.算法效率的概念: 掌握基本算法中枚举的概念: 掌握基本算法中递归的概念: 掌握自调用函数的应用,实现基本算法中的递归方法: 掌握基本算法中由递归变递推的方法: 能够使用 ...

  3. codeforce 227D Naughty Stone Piles (贪心+递归+递推)

    Description There are n piles of stones of sizes a1, a2, -, an lying on the table in front of you. D ...

  4. 基础算法 —— 递归/递推 —— 汉诺塔问题(Hanoi)

    [问题提出] Hanoi塔由n个大小不同的圆盘和三根木柱a,b,c组成.开始时,这n个圆盘由大到小依次套在a柱上,如图所示. 要求把a柱上n个圆盘按下述规则移到c柱上:  (1)一次只能移一个圆盘:  ...

  5. 递归--递推之组合数

    排列在上一篇中已经写到,是个典型的深搜题,下面是介绍的组合数, 组合的基本定义是, 但是除了用这种传统的方法来求,可以用递归的方式或者是递推的方式来求, 说道递推,只要会递归, 就会递推了.关键的一部 ...

  6. OJ2755神器的口袋 普通递归+递推+递推滚动数组

    代码如下: import java.util.Scanner; //神器的口袋 public class OJ2755 { static int[] weigth; static int[][] re ...

  7. 数字三角形(递归/递推)C/C++

    递归解法 分析: 这是一道经典的动态规划问题,我们还是从最浅显的算法出发,由浅到深慢慢研究.首先最容易想到的是暴力搜索算法.我们先用一个二维数组map来存放上面的数字三角形,于是有: map[1][1 ...

  8. 递归递推区别分析与例题总结

    递归与递推 文章目录 递归与递推 特点 递归(recursive) 递推(iterative) 例题 递推例子 平面分割问题 直线分割平面(基本结论) 线圈分割平面 折线分割平面 偷懒方法 Catal ...

  9. PTA—— 递归 递推

    个人名片: 博主:酒徒ᝰ. 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来. 专栏:PTA习题及解析 介绍:记录了博主在pta学习练题的一些方法与笔记. 目录 前言 1.简介 2.优点 一.题目 ...

最新文章

  1. Android-支持多屏幕[译文-2]
  2. sqlmap tamper脚本编写
  3. vue双向绑定原理源码解析
  4. 在Eclipse中打开Hadoop工程
  5. java计算时间跨度_请问如何使用Java计算时间跨度并格式化输出?
  6. ADO.NET连接数据库
  7. 自然语言处理-nltk学习(二)
  8. hash table(全域散列法实现的哈希表)
  9. 翻译 - EXT JS 5:Controlling an Application with Router
  10. 计算机硬件系统的安全,维护硬件系统的计算机安全论文
  11. mysql 三表left join_mysql left join 3表查询问题
  12. 51ctopython自动化测试工程师课程价格,Python自动化测试开发实战 一门能就业的测试课...
  13. 【SpringBoot_ANNOTATIONS】组件注册 03 FilterType
  14. 算法与数据结构(基于C语言)中线性表的快速排序快速查找
  15. 设计模式-行为性模式(模板方法模式,策略模式,命令模式,责任链模式,观察者模式,中介者模式,迭代器模式)
  16. 解决尝试连接“ECONNREFUSED - 连接被服务器拒绝”失败的问题
  17. EasyUI datagrid editor 中用filebox上传图片失败问题
  18. 论“搜狗”输入法对用户的影响
  19. android平板刷成windows,安卓系统的平板电脑可以刷成windows系统吗?
  20. 忘记本地mysql密码_本地MySQL密码忘了,怎么找回?

热门文章

  1. linux进程管理与调度
  2. activitimq集群搭建_Spring-activiti
  3. nvidia cuda工具包更新9.0版本记录
  4. Linux系统有线网络抓包程序
  5. html改变占位字符的颜色,使用CSS更改HTML5输入的占位符颜色
  6. 【java】Java运行时动态生成类几种方式
  7. 【java】如何在IDEA 中查看 Class文件的汇编
  8. 【Elasticsearch】基于 Elasticsearch + kibana 实现 IP 地址分布地图可视化
  9. 【高并发】怎么演示公平锁和非公平锁?
  10. 【java】Java 最坑爹的 10 大功能点