题目链接

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1

7 3

Sample Output

8

   分析:
设f(m,n) 为m个苹果,n个盘子的放法数目,则先对n作讨论,
当n>m:必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响。即if(n>m) f(m,n) = f(m,m)  
当n<=m:不同的放法可以分成两类:
1、有至少一个盘子空着,即相当于f(m,n) = f(m,n-1);
2、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即f(m,n) = f(m-n,n).
而总的放苹果的放法数目等于两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n)
递归出口条件说明:
当n=1时,所有苹果都必须放在一个盘子里,所以返回1;
当没有苹果可放时,定义为1种放法;
递归的两条路,第一条n会逐渐减少,终会到达出口n==1;
第二条m会逐渐减少,因为n>m时,我们会return f(m,m) 所以终会到达出口m==0.
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const ll LNF = 1e18;
const int maxn = 1e3 + 20;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
ll n,m;
double a[150];
ll f(ll n,ll m) //n个苹果 m个盘子
{
if(n==0 || m==1) return 1;
else
{
if(m>n) return f(n,n);
else return f(n,m-1)+f(n-m,m);
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
cout<<f(n,m)<<endl;
}
}

Disky and Sooma, two of the biggest mega minds of Bangladesh went to a far country. They ate, coded

and wandered around, even in their holidays. They passed several months in this way. But everything

has an end. A holy person, Munsiji came into their life. Munsiji took them to derby (horse racing).

Munsiji enjoyed the race, but as usual Disky and Sooma did their as usual task instead of passing some

romantic moments. They were thinking- in how many ways a race can finish! Who knows, maybe this

is their romance!

In a race there are n horses. You have to output the number of ways the race can finish. Note that,

more than one horse may get the same position. For example, 2 horses can finish in 3 ways.

  1. Both first
  2. horse1 first and horse2 second
  3. horse2 first and horse1 second

    Input

    Input starts with an integer T (≤ 1000), denoting the number of test cases. Each case starts with a

    line containing an integer n (1 ≤ n ≤ 1000).

    Output

    For each case, print the case number and the number of ways the race can finish. The result can be

    very large, print the result modulo 10056.

    Sample Input

    3

    1

    2

    3

    Sample Output

    Case 1: 1

    Case 2: 3

    Case 3: 13

    【题意】:给定n匹马,要求出可能的排名情况(可能并列)

    【分析】:组合数学+DP;

    假设n个人比赛时的名次种数为dp[n],假设第一名有i个,则有C(n,i)种可能——从n匹马选任意i个并列第一,接下来有dp[ n - i ]种可能性,运用乘法原理求组和;所以dp[ n ] += C[n,i] * dp[ n - i ] (注意!枚举i为1到n并且求和/加法原理)
递推公式:
f(n)= ∑ C(n,i)* f(n-i) (1≤ i ≤n)
f(0)=1
可以列出前几项,
n=1 f(1)=f(0)
n=2 C(2,1)*f(1)+C(2,2)*f(0)
n=3 C(3,1)*f(2)+C(3,2)*f(1)+C(3,3)*f(0)
…… 依次类推
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<(n); i++)
#define repe(i,x,n) for(int i=(x); i<=(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const int mod = 10056;
const ll LNF = 1e18;
const int maxn = 1e4;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
ll n,m;
ll a[maxn][maxn];
ll dp[maxn];
void init()
{
a[0][0]=1;
dp[0]=dp[1]=1;
repe(i,1,1000)
{
a[i][0]=1;
repe(j,1,i)
{
a[i][j]=(a[i-1][j]+a[i-1][j-1])%mod;
}
}
repe(i,2,1000)
{
for(int j=0;j<=i;j++)
{
dp[i]=(dp[i]+a[i][j]*dp[i-j])%mod;
}
}
}
int main()
{
init();
int t,cas=0;
scanf("%d",&t);
while(t--)
{
cin>>n;
cout<<"Case "<<++cas<<": "<<dp[n]<<endl;
}
}

在一次游戏中使用了N个盘子时,他需要多少次移动才能把他们都移到第三个柱子上?很显然,在没有第四个柱子时,问题的解是2^N-1,但现在有了这个柱子的帮助,又该是多少呢?

Input

包含多组数据,每个数据一行,是盘子的数目N(1<=N<=64)。

Output

对于每组数据,输出一个数,到达目标需要的最少的移动数。

Sample Input

1

3

12

Sample Output

1

5

81

【四柱汉诺塔】:

作者:酱紫君

链接:https://www.zhihu.com/question/24385418/answer/282940567

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三个盘子的汉诺塔你总会吧:



然后你移完发现左边柱子下面又蹦出来一个盘子

好吧, 那就把中间的柱子看成目标柱然后把最大的移到右边, 然后就和搬三个一模一样了更多的话也是一样的..

所以说一共就三步

把 n-1 号盘子移动到缓冲区

把1号从起点移到终点

然后把缓冲区的n-1号盘子也移到终点


变体汉诺塔

问题描述:在经典汉诺塔的基础上加一个条件,即,如果再加一根柱子(即现在有四根柱子a,b,c,d),计算将n个盘从第一根柱子(a)全部移到最后一根柱子(d)上所需的最少步数,当然,也不能够出现大的盘子放在小的盘子上面。注:1<=n<=64;

分析:设F[n]为所求的最小步数,显然,当n=1时,F[n]=1;当n=2时,F[n]=3;如同经典汉诺塔一样,我们将移完盘子的任务分为三步:

(1)将x(1<=x<=n)个盘从a柱依靠b,d柱移到c柱,这个过程需要的步数为F[x];

(2)将a柱上剩下的n-x个盘依靠b柱移到d柱(注:此时不能够依靠c柱,因为c柱上的所有盘都比a柱上的盘小)

些时移动方式相当于是一个经典汉诺塔,即这个过程需要的步数为2^(n-x)-1(证明见再议汉诺塔一);

(3)将c柱上的x个盘依靠a,b柱移到d柱上,这个过程需要的步数为F[x];

第(3)步结束后任务完成。

故完成任务所需要的总的步数F[n]=F[x]+2(n-x)-1+F[x]=2*F[x]+2(n-x)-1;但这还没有达到要求,题目中要求的是求最少的步数,易知上式,随着x的不同取值,对于同一个n,也会得出不同的F[n]。即实际该问题的答案应该min{2*F[x]+2^(n-x)-1},其中1<=x<=n;在用高级语言实现该算法的过程中,我们可以用循环的方式,遍历x的各个取值,并用一个标记变量min记录x的各个取值中F[n]的最小值。

数值不是很大,int完全可以搞定

【参考论文】:论文链接

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<(n); i++)
#define repe(i,x,n) for(int i=(x); i<=(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const int mod = 10056;
const ll LNF = 1e18;
const int maxn = 1e4;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int main()
{
int a[100],i,n,j;
a[1]=1;a[2]=3;
for(i=3;i<65;i++)
{
int min=99999999;
for(j=1;j<i;j++)
{
if(2*a[j]+pow(2.0,i-j)-1<min)
min=2*a[j]+pow(2.0,i-j)-1;
}
a[i]=min;
}
while(~scanf("%d",&n))
{
printf("%d\n",a[n]);
}
return 0;
}

We will construct an infinitely long string from two short strings: A = "__" (four characters), and B = "T.T" (three characters). Repeat the following steps:

Concatenate A after B to obtain a new string C. For example, if A = "__" and B = "T.T", then C = BA = "T.T__".

Let A = B, B = C -- as the example above A = "T.T", B = "T.T__".

Your task is to find out the n-th character of this infinite string.

Input

The input contains multiple test cases, each contains only one integer N (1 <= N <= 2^63 - 1). Proceed to the end of file.

Output

For each test case, print one character on each line, which is the N-th (index begins with 1) character of this infinite string.

Sample Input

1

2

4

8

Sample Output

T

.

^

T

【题意】:

设A="__"(4个字符),B="T,T"(3个字符),然后以AB为基础,构造无限长的字符串。重复规则如下:

(1)把A接在B的后面构成新的字符串C。例如,A="__",B="T.T", 则C=BA="T.T__"。

(2)令A=B,B=C,如上例所示,则A="T.T",B="T.T__"。

给出此无限长字符串中的第n个字符。

【分析】:

(1) 如果从字符串的长度考虑:

a=strlen("__") ->a=4

b=strlen("T.T) ->b=3

c=strlen("T.T__) ->c=7

再按照题目给定的步骤重复,我们就很容易发现,这正是以a,b为基数的斐波那契(Fibonacci)数列。

对于输入的正整数n,它对应的字符位于经过若干次按斐波那契数列的规律叠加后的字符串中。

无论字符串如何叠加,该位置的字符总是在字符串C中。【C=BA="T.T__"】

本题就变成给定一个正整数n,求出小于n的最大斐波那契数,n与该斐波那契数的差正是该字符在另一个更短的字符串C中的位置。 【C=BA="T.T__"】

输出时要注意,string类型的字符串的位置是从0开始编号的,所以用这个差值当下标时需要减去1!

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const ll LNF = 1e18;
const int maxn = 90;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
ll n,m;
ll a[maxn+5];
char *s="T.T^__^";
void init()
{
a[0]=4;
a[1]=3;
for(ll i=2;i<maxn;i++)
{
a[i] = a[i-1] + a[i-2];
}
}
int main()
{
init();
while(~scanf("%lld",&n))
{ while(n>7)
{
ll pos = lower_bound(a,a+maxn,n)-a;
n -= a[pos-1]; //n与该斐波那契数的差正是该字符在另一个更短的字符串C中的位置
}
printf("%c\n",s[n-1]);//字符串的位置是从0开始编号的,所以用这个差值当下标时需要减去1
}
}

7/26 CSU-ACM2018暑期训练3-递归&递推-选讲的更多相关文章

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

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

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

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

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

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

  4. 第二场周赛(递归递推个人Rank赛)——题解

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

  5. 2019暑期金华集训 Day6 杂题选讲

    自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...

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

  7. [ 9.26 ]CF每日一题系列—— 771B递推问题

    Description: 给定你命名的规律,1-10个字符,开头必须大写,最多有50个名字,然后告诉你有n个人,判断区间长度为k,那么你将得到n - k + 1个答案(YES or NO) 表示1 - ...

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

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

  9. Noip2019暑期训练2 反思

    经过两次测试,通过深刻的反思,我主要发现了以下易犯错误: 1.做题目时过于追求速度,导致好几处代码都出现手误打错的现象!而且,千万不要图快.图方便就复制粘贴,非常容易出错!(例如T3-party中直接 ...

随机推荐

  1. [洛谷P4782]【模板】2-SAT 问题

    题目大意:有$n$个布尔变量 $x_1 \sim x_n$,另有$m$个需要满足的条件,每个条件的形式都是"$x_i$ 为$true/false$或$x_j$为$true/false$&qu ...

  2. makefile使用笔记(一)入门

    By francis_hao    Mar 2,2017 makefile makefile一个很简单的例子如下,该实例完成在执行make时,将main.c编译成可执行文件main的功能. 各项的含义 ...

  3. c++ STL(2)

    Vector: #include "stdafx.h" #include<iostream> #include<vector> #include<al ...

  4. Spring学习--依赖注入的方式

    Spring 依赖注入: 属性注入(最常使用) 构造函数注入 工厂方法注入(很少使用,不推荐) 属性注入:通过 setter 方法注入 Bean 的属性值或依赖的对象 , 使用<property ...

  5. Git菜鸟

    1.git 和svn的差异 git和svn 最大的差异在于git是分布式的管理方式而svn是集中式的管理方式.如果不习惯用代码管理工具,可能比较难理解分布式管理和集中式管理的概念.下面介绍两种工具的工 ...

  6. 转:LVS负载均衡

    1.什么是LVS? 首 先简单介绍一下LVS (Linux Virtual Server)到底是什么东西,其实它是一种集群(Cluster)技术,采用IP负载均衡技术和 基于内容请求分发技术.调度器具 ...

  7. 记录一次Nginx跳转报错的问题

    错误信息如下: An error occurred. Sorry, the page you are looking for is currently unavailable. Please try ...

  8. codechef T2 Chef and Sign Sequences

    CHEFSIGN: 大厨与符号序列题目描述 大厨昨天捡到了一个奇怪的字符串 s,这是一个仅包含‘<’.‘=’和‘>’三种比较符号的字符串. 记字符串长度为 N,大厨想要在字符串的开头.结尾 ...

  9. 02-导航实例-storyboard实现

        源代码下载链接:02-导航实例-storyboard实现.zip38.5 KB // MJAboutViewController.h // //  MJAboutViewController. ...

  10. NYOJ 349 Sorting It All Out (拓扑排序 )

    题目链接 描述 An ascending sorted sequence of distinct values is one in which some form of a less-than ope ...