递推与递归——DP的前导

P1028 [NOIP2001 普及组] 数的计算 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

推导可知,f(n) = f(n-2) + f(n/2) = f(n-1) + f(n/2)

代码相当简洁

#include<iostream>
using namespace std;
int n;
int f[1005] = {0,1,2,2};//初始化前几个
int main(){
	cin>>n;
	for(int i = 3; i<=n; i++){
		if(i%2==1) f[i] = f[i-1];
		else f[i] = f[i-1]+f[i/2];//递归式
	}
	cout<<f[n];
	return 0;
}

P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

经典递归(搜索)问题:从n个数中选出k个数求和

递归:

  1. 能够将复杂问题分解为多个更简单的子问题
  2. 子问题求解方式和原问题相同
  3. 有终止条件

总问题:f(1,n,k) 从第一个数到第n个数,选k个数 ---->  f(2,n,k-1)选定第一个数,从第二个数到第n个数,选k-1个数...

这里的 f 递归式可用函数实现(有时可用数组实现)

#include<iostream>
using namespace std;
const int N = 25;
int n, k, res;
int a[N];
bool is_prime(int x){
	if(x<=1) return false;
	for(int i = 2; i<=x/i; i++){
		if(x%i==0) return false;
	}
	return true;
}
//从flag开始找,找num个数,总共和sum 
void f(int flag, int num, int sum){
	if(num==0){
		if(is_prime(sum)) res ++ ;
		return;
	}
	if(n-flag+1 < num) return;
	for(int i = flag; i<=n; i++){
		f(i+1, num-1, sum+a[i]);
	}
	return;
} 
int main(){
	cin>>n>>k;
	for(int i = 1; i<=n; i++) cin>>a[i];
	f(1,k,0);
	cout<<res;
	return 0;
}