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

正确的难度顺序为

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

一、种花

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

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

代码:

 #include <bits/stdc++.h>
using namespace std; int a[]; void init(){
a[] = ;
for(int i = ; i <= ; i++){
a[i] = a[i-]*;
}
} int main(){
freopen("test.out","w",stdout);
int n;
init();
while(cin>>n){
cout << a[n] << endl;
}
return ;
}

二、角谷定律

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

代码:

 #include <bits/stdc++.h>
using namespace std; int cnt = ;
void fun(long long n){
if(n == )
return ;
if(n&)
cnt++,fun(*n+);
else
cnt++,fun(n/);
} int main(){
int n;
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
while(cin>>n){
cnt = ;
fun(n);
cout << cnt << endl;
}
return ;
}

三、猴子和椰子

可能你们也在其他地方看见过本题,设初始椰子为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;

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

 #include <bits/stdc++.h>
using namespace std; long long fun(int n){
if(n == )
return ;
return *fun(n-)+;
} int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int n;
while(cin>>n){
cout << fun(n) << endl;
}
return ;
}

五、汉诺塔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;

代码:

 #include <bits/stdc++.h>
using namespace std; int fc(int n){
if(n == )
return ;
return *fc(n-)+;
} int fun(int n){
if(n == )
return ;
return *fc(n-)+;
} int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int n;
while(cin>>n){
cout << fun(n) << endl;
}
return ;
}

六、整数划分

其实这个题题面以及给出了一点提示,把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)

所以可以写出代码:

 #include <bits/stdc++.h>
using namespace std; int fun(int n,int m){
if(n == || m == )
return ;
else if(n < m)
return fun(n,n);
else if(n == m)
return fun(n,n-)+;
else if(n > m)
return fun(n,m-)+fun(n-m,m);
} int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int n;
while(cin>>n){
cout << fun(n,n) << endl;
}
cerr << clock() << endl;
return ;
}

七、跳台阶

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

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

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

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

代码:

 #include <bits/stdc++.h>
using namespace std; int prime[],primesize,phi[];
bool isprime[]; int n; void getlist(int listsize){
memset(isprime,,sizeof(isprime));
isprime[]=false;
for(int i=;i<=listsize;i++)
{
if(isprime[i])prime[++primesize]=i;
for(int j=;j<=primesize&&i*prime[j]<=listsize;j++)
{
isprime[i*prime[j]]=false;
if(i%prime[j]==)break;
}
}
prime[] = ;
} int fun(int n){
int sum = ;
if(n == || n == )
return ;
for(int i = ; i <= primesize; i++){
if(n < prime[i])
break;
sum += fun(n-prime[i]);
}
return sum;
} int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
ios_base::sync_with_stdio(false);
getlist();
int n;
while(cin>>n){
cout << fun(n) << endl;
}
cerr << clock() <<endl;
}

八、汉诺塔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根木棍需要的最小转移次数。

代码:

 #include <bits/stdc++.h>
using namespace std; int a[] = {}; int init(){
fill(a,a+,0x3f3f3f3f);
a[] = ,a[] = ,a[] = ;
for(int i = ; i <= ; i++){
for(int j = ; j < 32; j++){
temp = *a[j]+pow(2LL,(long long)j)-;
a[i] = min(a[i],temp);
}
}
} int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int n;
while(cin>>n){
int r = floor((sqrt(*n+)-1.0)/2.0);
int ans = (n-(r*r-r+)/2.0)*pow(2.0,r)+;
cout << ans << endl;
}
cerr << clock() << endl;
return ;
}

九、夏目友人帐(一)

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

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

代码:

 #include <bits/stdc++.h>
using namespace std; //线段树
#define lson l,m,p<<1
#define rson m+1,r,p<<1|1
#define Max(a,b) (a<b?b:a)
#define Min(a,b) (a<b?a:b)
#define INF 999999999 int N,M;
int MaxP[*+];
int maxT;
void Update(int val,int K,int l,int r,int p){
int m=(l+r)>>;
if(l==r){
MaxP[p]=val;
return;
}
if(K<=m)
Update(val,K,lson);
else
Update(val,K,rson);
MaxP[p]=Max(MaxP[p<<],MaxP[p<<|]);
}
void Query(int L,int R,int l,int r,int p){
int m=(l+r)>>;
if(L<=l&&r<=R){
maxT=Max(maxT,MaxP[p]);
return;
}
if(L<=m)
Query(L,R,lson);
if(R>=m+)
Query(L,R,rson);
}
int main(){
freopen("test2.in","r",stdin);
freopen("test2.out","w",stdout);
int i,val,a,b;
scanf("%d %d",&N,&M);
for(i=;i<=N;i++){
scanf("%d",&val);
Update(val,i,,N,);
}
for(i=;i<=M;i++){
scanf("%d %d",&a,&b);
maxT=;
Query(a,b,,N,);
printf("%d\n",maxT);
}
cerr << clock() << endl;
return ;
} //ST算法
int N,M;
int A[];
int FMax[][]; void Init(){
int i,j;
for(i=;i<=N;i++)
FMax[i][]=A[i];
for(i=;(<<i)<=N;i++){
for(j=;j+(<<i)-<=N;j++){
FMax[j][i]=max(FMax[j][i-],FMax[j+(<<(i-))][i-]);
}
}
} int Query(int l,int r){
int k=(int)(log(r-l+)/log());
return max(FMax[l][k],FMax[r-(<<k)+][k]);
} int main(){
freopen("test1.in","r",stdin);
freopen("test1.out","w",stdout);
int i,a,b;
scanf("%d %d",&N,&M);
for(i=;i<=N;i++)
scanf("%d",&A[i]);
Init();
for(i=;i<=M;i++){
scanf("%d %d",&a,&b);
printf("%d\n",Query(a,b));
}
cerr << clock() << endl;
return ;
}

十、夏目友人帐(二)

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

代码:

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll; const int N = ;
const int Q = ;
int f[Q][N][N];
int p[Q];
int c[N][N]; int main(){
freopen("test3.in","r",stdin);
freopen("test3.out","w",stdout);
ios_base::sync_with_stdio(false);
cin.tie();
cout.tie();
int n,q;cin>>n>>q;
for(int i = ; i <= n; i++){
for(int j = ; j <= n; j++){
cin>>c[i][j];
}
}
for(int i = ; i <= q; i++){
cin>>p[i];
}
memset(f,0x3f,sizeof(f));
int INF = f[][][];
p[] = ;
f[][][] = ;
for(int i = ; i <= q; i++){
for(int x = ; x <= n; x++){
for(int y = ; y <= n; y++){
if(x != p[i] && y != p[i])
f[i][x][y] = min(f[i][x][y],f[i-][x][y]+c[p[i-]][p[i]]);
if(p[i] != y && p[i] != p[i-])
f[i][p[i-]][y] = min(f[i][p[i-]][y],f[i-][x][y]+c[x][p[i]]);
if(p[i] != x && p[i] != p[i-])
f[i][x][p[i-]] = min(f[i][x][p[i-]],f[i-][x][y]+c[y][p[i]]);
}
}
}
int ans = INF;
for(int i = ; i<= n; i++){
for(int j = ; j<= n; j++){
ans = min(ans,f[q][i][j]);
}
}
cout << ans << endl;
cerr << clock() << endl;
return ;
}

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

第二场周赛(递归递推个人Rank赛)——题解的更多相关文章

  1. 蓝桥杯—BASIC-21 sine之舞(递归递推)

    题目:最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数,所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力. 不妨设 An=sin(1– ...

  2. 再谈循环&迭代&回溯&递归&递推这些基本概念

    循环:不断重复进行某一运算.操作. 迭代:不断对前一旧值运算得到新值直到达到精度.一般用于得到近似目标值,反复循环同一运算式(函数),并且总是把前一 次运算结果反代会运算式进行下一次运算 递推:从初值 ...

  3. 【Java】递归递推的应用

    利用阶乘公式来计算组合式: 程序设计思想: 根据公式来计算组合数的大小,从键盘输入n,k的值,设计一个计算阶乘的大小,如果输入的数a为1或0,则直接return 1,否则运用递归,计算a-1的阶乘,直 ...

  4. 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 ...

  5. 蓝桥杯—ALGO-12 幂方分解(递归递推)

    问题描述 任何一个正整数都可以用2的幂次方表示.例如: 137=27+23+20 同时约定方次用括号来表示,即ab 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+2(0) 进一步 ...

  6. 2019牛客多校第二场E MAZE(线段树 + 矩阵)题解

    题意: n * m的矩阵,为0表示可以走,1不可以走.规定每走一步只能向下.向左.向右走.现给定两种操作: 一.1 x y表示翻转坐标(x,y)的0.1. 二.2 x y表示从(1,x)走到(n,y) ...

  7. 2019牛客多校第二场F Partition problem(暴搜)题解

    题意:把2n个人分成相同两组,分完之后的价值是val(i, j),其中i属于组1, j属于组2,已知val表,n <= 14 思路:直接dfs暴力分组,新加的价值为当前新加的人与不同组所有人的价 ...

  8. CodeForces 429 B Working out(递推dp)

    题目连接:B. Working out 我想了很久都没有想到怎么递推,看了题解后试着自己写,结果第二组数据就 wa 了,后来才知道自己没有判选择的两条路径是否只是一个交点. 大概思路是:先预处理出每个 ...

  9. NOIP 2008 传纸条(洛谷P1006,动态规划递推,滚动数组)

    题目链接:P1006 传纸条 PS:伤心,又想不出来,看了大神的题解 AC代码: #include<bits/stdc++.h> #define ll long long using na ...

随机推荐

  1. ABAP_增强点查找

    *&---------------------------------------------------------------------* *& Report Z_FIND_EN ...

  2. if else 深度优化

    一. if else表达式过于复杂 if ((condition1 && condition2 ) || ((condition2 || condition3) && ...

  3. 前端面试题集锦(一)之HTML部分

    前端的发展日新月异,前端开发也早已从原来的切图套页面,变成了现在的非常复杂的技术体系,近期由于找工作,面试了很多家单位,也总结了一部分前端面试中经常会遇到的面试类型,并一一解答.主要分为HTML.CS ...

  4. 项目启动会(project initiating meeting)与项目开工会(kick-off meeting)区别

    一.项目启动会initiating meeting 召开时间:是启动阶段结束时召开的会议:主要任务:发布项目章程,并任命项目经理,赋予项目经理动用组织资源的权力:注意事项:(1)会议召开前已经对干系人 ...

  5. Java笔记(持续更新中)

    Java语言的特点: 面向对象(封装,继承,多态) 平台无关性(JVM运行.class文件) 语言(泛型,Lambda) 类库(集合,并发,网络,IO/NIO) JRE(Java运行环境,JVM,类 ...

  6. Zabbix监控华为路由器配置

    zabbix监控华为路由器 一.配置路由器界面: 开启snmpv2c功能,同时勾选v2c版本(不要勾v1,不安全,其实v2也不安全,如果很注重安全的话,一定要只配置v3). 手里没有路由器登录账号,大 ...

  7. VR、AR、MR、CR 与 AI与SaaS、CRM、MRP与B2B、B2C、C2C、O2O、P2P

    一.VR.AR.MR.CR  VR ( Virtual Reality ),虚拟现实 AR(Augmented Reality),增强现实 MR(Mix Reality),混合现实 CR(Cinema ...

  8. CSS布局:元素水平垂直居中

    CSS布局:元素水平垂直居中 本文将依次介绍在不同条件下实现水平垂直居中的多种方法 水平垂直居中是在写网页时经常会用到的需求,在上两篇博客中,分别介绍了水平居中和垂直居中的方法.本文的水平垂直居中就是 ...

  9. CentOS重置MySQL root密码的方法

    1.修改MySQL的登录设置: # vim /etc/my.cnf 在[mysqld]的段中加上一句:skip-grant-tables 例如: [mysqld] skip-grant-tables  ...

  10. [Python] Django框架入门3——深入视图

    说明: 本文主要深入了解视图(views.py),涉及路由配置.定义视图.Request对象.Response对象.状态保持等. 一.路由配置 1.配置位置(settings.py 的 ROOT_UR ...