递推求解专题练习(For Beginner)

链接http://acm.hdu.edu.cn/search.php?field=problem&key=%B5%DD%CD%C6%C7%F3%BD%E2%D7%A8%CC%E2%C1%B7%CF%B0%A3%A8For+Beginner%A3%A9&source=1&searchmode=source

HDU2044 一只小蜜蜂…

#include<iostream>
using namespace std;
long long a[100];
void digui() {
	a[0] = 0;
	a[1] = 0;
	a[2] = 1;
	a[3] = 2;
	for(int i = 4; i < 100; i++) {
		a[i] = a[i-1] + a[i-2];
	}
}
int main() {
	digui();
	int N;
	int aa,bb;
	scanf("%d",&N);
	while(N--) {
		scanf("%d%d",&aa,&bb);
		printf("%lld\n",a[bb-aa+1]);
	}
}

阿牛的EOF牛肉串

#include<iostream>
using namespace std;
long long dp[100] = {0};
//RPG看 n-1  而这道题靠n 出发为两种情况。 
int main() {
	int N;
	dp[1] = 3;
	dp[2] = 8;
	//n放o n-1只能放2种,那么就是n-2 成2
	//n不放o ,可以放2种,那么n-1 乘2即可
	for(int i = 3; i < 100; i++) {
		dp[i] = 2*(dp[i-1]+dp[i-2]);
	}
	while(scanf("%d",&N)!=EOF) {
		printf("%lld\n",dp[N]);
	}
}

不容易系列之(3)—— LELE的RPG难题

//RGB颜色
//首先可以知道,
//f1 f2 f3 的情况分别为 3 6 6;
//递推式的选择,可以明显的知道  当n-1与首颜色一样,则
// n的颜色有n-2 的差乘2;当n-1与首颜色不一样,那么n只能有一种选择
//那么这时候n的情况与n-1的情况一致
#include<iostream>
using namespace std;
long long  dp[100] = {0};
int main(){
	dp[1] = 3;
	dp[2] = 6;
	dp[3] = 6;
	for(int i = 4; i < 100;i++){
		dp[i] = dp[i-1] + dp[i-2]*2;//n-1理论上只可能会有 与首不同的方案,所以考虑n-2的时候假使了n-1可以与首相同的情况。 
	}
	int N;
	while(scanf("%d",&N)!=EOF){
		printf("%lld\n",dp[N]);
	}
	return 0;
} 

不容易系列之(4)——考新郎

#include<iostream>
using namespace std;

//这道题实际上一看就是排错问题,问题在于,它不是求全部排错的情况
//而是求部分错,那么可以看成CMN=N!/(M!*(N-M)!)的问题,即挑选出M个新郎
//让这些新郎都排错,,,组合有多少种,即站的位置
//dp【m】代表的是1—M这按序号的M个新郎,注意是前M个,全部排错的次数
//那么即使不是前M个,排错的次数也一定是一样的,比如 2-M+1
long long dp[100]= {0};
long long  sum[100] = {0};
int main() {
	int N;
	dp[0] = 0;
	dp[1] = 0;//完全错了 
	dp[2] = 1;//完全错了 
	for(int i = 3; i < 100; i++) {
		dp[i] = (i-1)*(dp[i-1] + dp[i-2]);
	}
	sum[0] = 1;//偷懒的后果 
	sum[1] = 1;
	sum[2] = 2;
	for(int i =3; i < 100; i++) {
		sum[i] = i*sum[i-1];
	}
	int M,k;
	scanf("%d",&N);
	while(N--) {
		scanf("%d %d",&M,&k);
		printf("%lld\n",sum[M]/sum[k]/sum[M-k]*dp[k]);
	}
}

超级楼梯

#include<iostream>
//http://acm.hdu.edu.cn/showproblem.php?pid=2041
using namespace std;
long long P[100];
void digui() {
	P[0] = 0;
	P[1] = 0;
	P[2] = 1;
	P[3] = 2;
	for(int i =4; i < 100; i++) {
		P[i] = P[i-2] + P[i-1];
	}
}
int main() {
	digui();
	int N;
	scanf("%d",&N);
	int a;
	while(N--) {
		scanf("%d",&a);
		printf("%lld\n",P[a]);
	}
}

骨牌铺方格

#include<iostream>
using namespace std;
long long dp[100] = {0};
//只可能出现的情况是,竖着放还是横着放,这是确定的。 
int main() {
	dp[1] = 1;
	dp[2] = 2;
	dp[3] = 3;
	for(int i = 4; i < 100; i++)
		dp[i] = dp[i-1]+dp[i-2];
	int N;
	while(scanf("%d",&N)!=EOF) {
		printf("%lld\n",dp[N]);
	}
	return 0;
}

神、上帝以及老天爷

#include<iostream>
using namespace std;
//解决题目问题只需要:n个人错排种类/n个人总排列种类(n!)
//f ( n ) 为 n 个人拿的都不是自己的票的拿票方法数
//假设有N - 1 个人满足错排(每个人拿的都不是自己的票),再来一个人(他手中拿的是自己的票),
//他与前 N - 1 中任何一个人交换票,都能满足N个人的错排。这时的的方法数为 (n - 1)* f ( n - 1)
//假设有 N - 1 个人不满足错排, 当来了一个人时,他与这 N - 1 个人中的其中一个交换后,
//满足 N 个人的错排。这种情况在原先 N - 1 个人中, 有 N - 2个人满足错排,只有一个人拿着自己的票,
//当这个拿着自己票的人与来了的这一个人交换后,就满足了N个人的的错排。而这只有一个拿着自己票的人可
//以是N - 1 个人中的任意一个。所以,这是的方法数为 (n - 1)* f( n - 2)
double dp[100] = {0};
int main() {
	int N;
	dp[1] = 0;
	dp[2] = 1;
	for(int i =3; i < 100; i ++) {
		dp[i] = (i-1)*(dp[i-2]+dp[i-1]);
		//即造成此时放下去是错排的情况只可能有2种
	}
	double   sum[100] = {0};//这里需要注意 
	sum[1] = 1;
	for(int i = 2; i < 100; i++) {
		sum[i] = i*sum[i-1];
	}
	int N2;
	
	scanf("%d",&N2);
	
	while(N2--) {
		int N;
		scanf("%d",&N);
		printf("%.2lf%%\n",(dp[N]/sum[N])*100);
	}
	
}

发布了154 篇原创文章 · 获赞 4 · 访问量 8620

猜你喜欢

转载自blog.csdn.net/weixin_38023259/article/details/105309846