递推测试总结及题解

哈哈

一定不是萌新发帖啦!!!

话不多说,直接进入正题:

1.舞蹈毯

题目描述

由于长期缺乏运动,小黑发现自己的身材臃肿了许多,于是他想健身,更准确地说是减肥。

小黑买来一块圆形的毯子,把它们分成三等分,分别标上A、B、C,称之为“跳舞毯”,他的运动方式是每次都从A开始跳,每次都可以任意跳到其他块,但最后必须跳回A,且不能原地跳.为达到减肥效果,小黑每天都会坚持跳N次,有天他突然想知道当他跳次时共几种跳法,结果想了好几天没想出来。

现在就请你帮帮他,算出总共有多少跳法。

  • 输入格式 测试输入包含若干测试用例。每个测试用例占一行,表示N的值。当N为0时输入结束。

  • 输出格式 每个测试用例的输出占一行,由于跳法非常多,输出其对10000取模的结果

样例输入

2
3
4
0

样例输出

2
2
6

数据范围与提示

1 <= n <= 1000

分析

首先,我们知道递推一般是最后一步来找公式,就如这道水的不能再水的经典题

先观察

N次有a[n]种情况,我们发现,若第N次后要回到A,那么第N-2次就会有2种情况:

  1. N-2A时,可从AB再返回A或到C再返回A,则有2种情况,又因为这两种情况回A都需两步,即:共有 *a(n-2)2 种情况
  2. N-2B或C时,跳回A都只有一种情况,即:有 a[n-1] 种情况。

代码如下AC不了别找我

    #include<cstdio>

    int main(){	
	    int n[1005]={},x;
	    n[2]=2;
	    n[3]=2;
	    for(int j=4;j<=1000;j++){
		    n[j]=(n[j-1]+n[j-2]*2)%10000;
	    }
	    while(scanf("%d",&x)!=EOF&&x){
		    printf("%d\n",n[x]);
	    }
	    return 0;
    }

2. 集合的和

好难好难好难

太“水”了~~~~

题目描述

农夫约翰命令他的牛去寻找不同的集合,这些集合里面的数字加起来刚好等于农夫约翰给定的数字n,而且集合里面的数字只能是2的次方。例如,农夫约翰给定的数字为7,则这些不同的集合一共有6个,分别如下:

1+1+1+1+1+1+1

1+1+1+1+1+2

1+1+1+2+2

1+1+1+4

1+2+2+2

1+2+4

请你帮助农夫约翰数出对于数字n来说,一共有多少个这样不同的集合?

  • 输入格式 输入有多组测试数据,每组测试数据有一行,包含一个整数n,表示农夫约翰所给定的数字。

  • 输出格式 对于每组测试数据输出只有一行,包含一个整数,表示对于数字n来说,不同的集合的个数。由于这个数字可能非常的大,对结果取模1e9

样例输入

7
10000

样例输出

6
573449444

数据范围与提示

1<=N<=1,000,000

分析

这道题十分简单:
首先,

把第N个集合个数看成a[n]

然后:

1.我们知道:除1外,所有奇数的集合都等于其前一个偶数的集合个数

2.把N看成N-1和1,则:

1.若N-1本身就可以凑成集合,那么+1就不会对其造成影响(因为1就是2的幂),就有a[n-1]种情况;

2.若N-1不能凑出集合,那么就会多出一个1来,和后面的1一加,就没有一了,此时的个数和N/2的个数一样(因为每个数字除以2并不影响总集合个数),就有a[n/2]种情况。

综上所述

亮代码!错了也不能怪我

#include <cstdio>
int a[10000005];     //定义全局,否则会爆
int main(){
  int n;
  a[1]=1;
  for(int i=2;i<=10000000;i++) { 
    if(i%2==0) 
		  a[i]=(a[i-1]+a[i/2])%1000000000; 
    else
	 	  a[i]=a[i-1]%1000000000;         //也可以放后面一起模
  }
  while(scanf("%d",&n)!=EOF) 
		printf("%d\n",a[n]);
  return 0;
}

3.帖瓷砖

题目描述

现有2×1大小的瓷砖若干个,现在要使用这些瓷砖来铺一条宽度为3,长为n的小路,请问一共有多少种贴法?

  • 输入格式 输入有多组测试数据,每组测试数据包含一个整数n

  • 输出格式 每组测试数据输出1个整数,表示当前长度的小路的贴法总数。

样例输入
2
8
12
样例输出
3
153
2131
数据范围与提示
1<=N<=30

分析

设:第N个贴法总数a[n]个。
  1. 奇数不可能

  2. 偶数:

    1.a[n]=3a[n-2]+2a[n-4]+2a[n-6]+…+2a[2]+2*a[0];

    2.a[n-2]=3a[n-4]+2a[n-6]+…+2a[2]+2a[0]

    3.a[n]-a[n-2]=3*a[n-2]-a[n-4]

    化简得:

    4.a[n]=4*a[n-2]-a[n-2]

这就是通项公式!!!

代码如下依旧不敢保证AC

#include<cstdio>

int main(){
	long long n[35]={};
	int x;
	n[2]=3;                    
	n[4]=11;                       //2项和4项需要赋初值,因为公式对它们没用
	for(int i=5;i<=30;i++){
		if(i%2==0)
			n[i]=4*n[i-2]-n[i-4];
	}
	while (scanf("%d",&x)!=EOF)
		printf("%d\n",n[x]);
	return 0;
}

4.分糖果

题目描述

马老师要把N颗糖果分给K个学生,并且要保证每个学生都能分到糖果,问一共有多少种不同的分配方案?例如:N=5,K=3,共有6种不同的方案。

5=1+2+2 

5=1+3+1

5=2+1+2

5=2+2+1

5=3+1+1
  • 输入格式 仅有一行,包含两个用空格隔开的自然数N和K。

  • 输出格式 只有一行,包含一个整数,表示将N颗糖果分给K个学生的方案总数,具体方案不需要输出。

样例输入

5 3

样例输出

6

数据范围:

N<=200,K<=10

分析

  1. 将N颗糖果分给K个学生的方案总数表示为a[i][j],其中i=学生数,j=糖果数;

  2. a[i][i]和a[1][j]的初值都为1(糖果数和人数相等,每人有且只有1颗;人数唯一,所有糖归他)

  3. 如下:

    1.a[i][j]=a[i-1][j-1]+a[i-1][j-2]+…+a[i-1][i-1]

    2.a[i][j-1]=a[i-1][j-2]+a[i-1][j-3]+…+a[i-1][i-1]

    3.a[i][j]-a[i][j-1]=a[i-1][j-1]

    化简得:

a[i][j]=a[i][j-1]+a[i-1][j-1]

通项公式又出来啦!!!

所以,是时候亮出最后的代码啦:

虽然完美撒花但我仍不保证代码的正确性

#include<cstdio>
long long n,k,a[15][205];
int main(){	
	scanf("%lld %lld",&n,&k);
	for(int i=1;i<=10;i++){
		a[i][i]=1;	
	}
	for(int i=1;i<=200;i++){
		a[1][i]=1;
	}
	for(int i=2;i<=10;i++){
		for(int j=2;j<=200;j++){
			a[i][j]=a[i][j-1]+a[i-1][j-1];
		}
	}
	printf("%lld",a[k][n]);
	return 0;
}

★,°:.☆( ̄▽ ̄)/$:.°★。撒花!

猜你喜欢

转载自blog.csdn.net/xf2056188203/article/details/106941974
今日推荐