递归

///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                      |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.

HDU 2013

A.蟠桃记
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem Description
喜欢西游记的同学肯定都知道悟空偷吃蟠桃的故事,你们一定都觉得这猴子太闹腾了,其实你们是有所不知:悟空是在研究一个数学问题!
什么问题?他研究的问题是蟠桃一共有多少个!
不过,到最后,他还是没能解决这个难题,呵呵^ - ^
当时的情况是这样的:
第一天悟空吃掉桃子总数一半多一个,第二天又将剩下的桃子吃掉一半多一个,以后每天吃掉前一天剩下的一半多一个,到第n天准备吃的时候只剩下一个桃子。聪明的你,请帮悟空算一下,他第一天开始吃的时候桃子一共有多少个呢?

Input
输入数据有多组,每组占一行,包含一个正整数n(1<n<30),表示只剩下一个桃子的时候是在第n天发生的。

Output
对于每组输入数据,输出第一天开始吃的时候桃子的总数,每个测试实例占一行。

Sample Input
2
4

Sample Output
4
22

题解:
我们知道猴子每天吃掉一半多一个的桃子,那么假设,第i天有f[i]个桃子,那么第i+1天就有 f [ i ] 2 \frac{f[i]}{2} 2f[i]-1个。
我们已知第n天只剩一个桃子,那么我们就可以逆推前一天有2*(f[n]+1)个,递推即可求出答案


AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
int f(int n)
{
    if (n == 1)
        return 1;
    else
        return 2 * (f(n - 1) + 1);
}
int main()
{
    int n,m;
    while (scanf("%d",&n)!=EOF)
    {
        m = f(n);
        printf("%d\n",m);
    }
    return 0;
}

HDU 4472

B.Count
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
Prof. Tigris is the head of an archaeological team who is currently in charge of an excavation in a site of ancient relics.
This site contains relics of a village where civilization once flourished. One night, examining a writing record, you find some text meaningful to you. It reads as follows.
“Our village is of glory and harmony. Our relationships are constructed in such a way that everyone except the village headman has exactly one direct boss and nobody will be the boss of himself, the boss of boss of himself, etc. Everyone expect the headman is considered as his boss’s subordinate. We call it relationship configuration. The village headman is at level 0, his subordinates are at level 1, and his subordinates’ subordinates are at level 2, etc. Our relationship configuration is harmonious because all people at same level have the same number of subordinates. Therefore our relationship is …”
The record ends here. Prof. Tigris now wonder how many different harmonious relationship configurations can exist. He only cares about the holistic shape of configuration, so two configurations are considered identical if and only if there’s a bijection of n people that transforms one configuration into another one.
Please see the illustrations below for explanation when n = 2 and n = 4.在这里插入图片描述
The result might be very large, so you should take module operation with modules 109 +7 before print your answer.

Input
There are several test cases.
For each test case there is a single line containing only one integer n (1 ≤ n ≤ 1000).
Input is terminated by EOF.

Output
For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) and Y is the desired answer.

Sample Input
1
2
3
40
50
600
700

Sample Output
Case 1: 1
Case 2: 1
Case 3: 2
Case 4: 924
Case 5: 1998
Case 6: 315478277
Case 7: 825219749

题意:
有n个点,使之构成一个树,要求每一层的每个节点的子节点数要相同。问有多少中构造法。

题解:
对于n个点,先将第一个节点(父节点)去掉,因为父节点只有一个,还剩下 n-1 个点。
因为每一层的每个节点的子节点数要相同,所以将这 n-1 个节点m等分,每份为(n-1)/m个点,
再递归求解即可;

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int mod=1e9+7;
int dp[1100];
int n;
int main()
{
  dp[1]=1;
  dp[2]=1;
  dp[3]=2;
  for(int i=4;i<1010;i++)
  {
    for(int j=1;j<=i;j++)
    {
      if((i-1)%j==0)
      {
        dp[i]+=dp[(i-1)/j];
        dp[i]%=mod;
      }
    }
  }
  int ca=0;
  while(~scanf("%d",&n))
  {
    printf("Case %d: %d\n",++ca,dp[n]);
  }
  return 0;
}

HDU 2044

C.一只小蜜蜂...
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem Description
有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。
其中,蜂房的结构如下所示。
在这里插入图片描述

Input
输入数据的第一行是一个整数N,表示测试实例的个数,然后是N 行数据,每行包含两个整数a和b(0<a<b<50)。

Output
对于每个测试实例,请输出蜜蜂从蜂房a爬到蜂房b的可能路线数,每个实例的输出占一行。

Sample Input
2
1 2
3 6

Sample Output
1
3

题解:
看图可知,由于蜜蜂每次只能从前1个蜂房前2个蜂房过来,那么f(n)=f(n-2)+f(n-1)。就是一个菲波拉契数列。

AC代码:

#include<iostream>
#define ll long long
using namespace std;
ll f[500];
int main()
{
    int N, a, b,c;
    ll n;
    f[1]=1;
    f[2]=2;
    for (int i = 3; i <=50; i++) 
    {
        f[i]=f[i - 1]+f[i - 2];
    }
    cin >> N;
    while (N--)
    {  
        cin >> a >> b;
        c = b - a;
        n = f[c];
        cout << n << endl;
    }
    return 0;
}

HDU 1865

D.1sting
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
You will be given a string which only contains ‘1’; You can merge two adjacent ‘1’ to be ‘2’, or leave the ‘1’ there. Surly, you may get many different results. For example, given 1111 , you can get 1111, 121, 112,211,22. Now, your work is to find the total number of result you can get.

Input
The first line is a number n refers to the number of test cases. Then n lines follows, each line has a string made up of ‘1’ . The maximum length of the sequence is 200.

Output
The output contain n lines, each line output the number of result you can get .

Sample Input
3
1
11
11111

Sample Output
1
2
8

题意:
将一串全是1的字符串合并,连续的两个1可以合并成2,问你长度为n的字符串最多有几种合并方法。

题解:
假设长度为n的数字结果为f(n)
则f(n+1)有两种可能
1.合并后末尾为1,就相当于长度为n的全1序列的合并的结果
2.合并后末尾为2,就相当于长度为n-1的全1序列的合并的结果

所以:f(n+1)=f(n)+f(n-1);

数据结果过大,所以要用大数加法模拟

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int s[250][50];//这里面我定义的数字为最长为50位,害怕不够的可以定义的大些,不过第200项的数位是22位
int t;
char str[250];
int main()
{
    s[1][0] = 1;
    s[2][0] = 2;
    s[3][0] = 3;
    for(int i = 4;i < 201;i++)
    {
        int tmp = 0;
        for(int j = 0;j < 50;j++)
        {
            s[i][j] = s[i - 1][j] + s[i - 2][j] + tmp;
            tmp = 0;
            if(s[i][j] > 9 && j < 49)
            {
                tmp = s[i][j]/10;
                s[i][j] = s[i][j]%10;
            }
        }
    }
    cin >> t;
    while(t--)
    {
        cin >> str;
        int flag = 0;
        int len=strlen(str);
        for(int i = 49;i >= 0;i--)
        {
            if(s[len][i] == 0 && flag == 0)//  除去前面的 0
            {
                continue;
            }
            flag = 1;
            cout << s[len][i];
        }
        cout << endl;
    }
    return 0;
}

HDU 1016

E.Prime Ring Problem
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, …, n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.

Input
n (0 < n < 20).

Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.

Sample Input
6
8

Sample Output
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

题意:
很容易理解,就是让你输出满足相邻的相加是素数的序列(注意不要重复)

题解:
深搜+回溯

AC代码:

 #include<iostream>
 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 #define N 50
 int a[N],n,vis[N];//vis判断数组是否被使用过
 bool is_prime(int x) //判断素数
 {
     if(x==1||x==2) return true;
     if(x%2==0) return false;
     for(int i=3; i*i<=x; i=i+2)
   	 {
         if(x%i == 0)
           return false;
     }
     return true;
 }
void dfs(int step)
{
  if(step==n+1&&(is_prime(a[1]+a[n])==true))
  {
    for(int i=1;i<n;i++)
    {
      printf("%d ",a[i]);
    }
    printf("%d\n", a[n]);
    return ;
  }
  for(int i=2;i<=n;i++)
  {
    if(vis[i]==0&&is_prime(a[step-1]+i)==true)
    {
      vis[i]=1;
      a[step]=i;
      dfs(step+1);
      vis[i]=0;
    }
  }
}
int main()
{
  int c=1;
  a[1]=1;
  while(~scanf("%d",&n))
  {
    memset(vis,0,sizeof(vis));
    printf("Case %d:\n",c++);
    dfs(2);
    printf("\n");
  }
  return 0;
}

HDU 1021

F.Prime Ring Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem Description
There are another kind of Fibonacci numbers: F(0) = 7, F(1) = 11, F(n) = F(n-1) + F(n-2) (n>=2).

Input
Input consists of a sequence of lines, each containing an integer n. (n < 1,000,000).

Output
Print the word “yes” if 3 divide evenly into F(n).
Print the word “no” if not.

Sample Input
0
1
2
3
4
5

Sample Output
no
no
yes
no
no
no

题意:
斐波那契数组,判断每个数能否被3整除

题解:
每个数组存除以3的模,等于0就是能被整除。
(a+b)%3=(a%3+b%3)%3;

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
  int f[1000005];
  f[0]=1;
  f[1]=2;
  for(int i=3;i<1000005;i++)
  {
    f[i]=(f[i-1]+f[i-2])%3;
  }
  int n;
  while(~scanf("%d",&n))
  {
    if(f[n]==0)
    {
      printf("yes\n");
    }
    else
    {
      printf("no\n");
    }
  }
  return 0;
}

HDU 2266

G.How Many Equations Can You Find
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
Now give you an string which only contains 0, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9.You are asked to add the sign ‘+’ or ’-’ between the characters. Just like give you a string “12345”, you can work out a string “123+4-5”. Now give you an integer N, please tell me how many ways can you find to make the result of the string equal to N .You can only choose at most one sign between two adjacent characters.

Input
Each case contains a string s and a number N . You may be sure the length of the string will not exceed 12 and the absolute value of N will not exceed 999999999999.

Output
The output contains one line for each data set : the number of ways you can find to make the equation.

Sample Input
123456789 3
21 1

Sample Output
18
1

题意:
本题给出我们一个数字串,可以在适当的位置添加“+”或者“-”号,使得运算的结果等于给出的n;

题解:
dfs,考虑已经处理的数字的个数和当前这部分的值,处理到终点时,如果等于n,结果+1.

AC代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
ll num,n,len;
char str[15];
void dfs(ll x,ll sum)
{
    if(x==len)
    {
        if(sum==n)
        {
          num++;
          return ;
        }
    }
    ll k=0;
    for(int i=x;i<len;i++)
    {
        k=k*10+str[i]-'0';
        dfs(i+1,sum+k);
        if(x!=0)//第一个数字前不能加“-”号
          dfs(i+1,sum-k);
    }
}
int main()
{
    while(scanf("%s %lld",str,&n)!=EOF)
    {
        len=strlen(str);
        num=0;
        dfs(0,0);
        printf("%lld\n",num);
    }
    return 0;
}

HDU 2553

H.N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input
1
8
5
0

Sample Output
1
92
10

AC代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int val[12][12];
int ans,t;
bool safety(int n,int m)
{
  for(int i=1;i<n;i++)
  {
    for(int j=1;j<=t;j++)
    {
      if(val[i][j]!=0&&(j==m||abs(i-n)==abs(j-m)))//同一列或者45°的情况
      {
        return false;
      }
    }
  }
  return true;
}
void queen(int l)
{
  if(l>t)
  {
    ans++;
    return;
  }
  for(int i=1;i<=t;i++)
  {
    val[l][i]=1;
    if(safety(l,i)==true)
    {
      queen(l+1);
    }
    val[l][i]=0;
  }
}
int main()
{
  int f[11];
  int n;
  for(int i=1;i<=10;i++)
  {
    t=i;
    ans=0;
    queen(1);
    f[i]=ans;
  }
  while(scanf("%d",&n)&&n)
  {
    printf("%d\n", f[n]);
  }
  return 0;
}


POJ 1664

放苹果
Time Limit: 1000MS Memory Limit: 10000K

Problem Description
把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

Sample Input
1
7 3

Sample Output
8


题解:
1.假设最少的盘子最少放一个苹果,其余的盘子就都得放一个苹果,那么就分掉n个苹果,剩余的m-n个苹果可以随便放;

2.假设最少的盘子没有放,那么就是m个苹果再n-1个盘子里随便放。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define ll long long
int t,n,m;
int f(int m,int n)
{
  if(m<0) return 0;
  if(m==0||n==1) return 1;
  return f(m-n,n)+f(m,n-1);
}
int main()
{
  scanf("%d",&t);
  while(t--)
  {
    scanf("%d%d",&m,&n);
    printf("%d\n",f(m,n));
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值