这四题用递归写法:数据量
40--50
可能就跑不动了
所以这里涉及一个记忆化的小技巧
因为递归是一直递归到最后的结束条件,所以有些不用递归到最后
就可以结束了,比如我们要求6的阶乘,第一次求了6的阶乘,我们再
准备求3的阶乘的时候,其实已经不用求了,因为在求6的阶乘的时候
已经把3的阶乘求过了
看一下代码理解一下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 1005
ll dp[maxn];//做记忆化的辅助数组
ll s_mul(ll n)//阶乘
{
if(n==0)//0的阶乘是1
return 1;
dp[n]=n*s_mul(n-1);
}
int main()
{
ll n;
n=20;
s_mul(n);//相当于预处理
int t;
scanf("%d",&t);
while(t--)
{
ll x;
scanf("%lld",&x);
printf("%lld\n",dp[x]);
}
puts("\n");
}
看一下结果:共20组,从1到20的阶乘结果
我写上面这个代码的过程,是因为对于下面有的题解可能有人不太理解的,所以对记忆化进行解释,对递归的结束条件适当的修改会减少时间的复杂度,有些就不用递归到最后一层去找答案,因为在之前的递归中已经找到了答案,我们只需要把答案存起来即可,当用到的时候拿来用即可
神考一:
#include<cstdio>
using namespace std;
#define ll long long
#define maxn 1005
ll dp[maxn];
ll pass(ll x)
{
if(dp[x])
return dp[x];
if(x==1||x==2)
return 1;
return dp[x]=pass(x-2)+pass(x-1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n;
scanf("%lld",&n);
ll ans=pass(n);
printf("%lld\n",ans);
}
}
神考二:
#include<cstdio>
using namespace std;
#define ll long long
#define maxn 1005
ll dp[maxn];
ll pass(ll x)
{
if(x==0)
return 3;
return (pass(x-1)-1)*2;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n;
scanf("%lld",&n);
ll ans=pass(n);
printf("%lld\n",ans);
}
}
神考三:
#include<cstdio>
using namespace std;
#define ll long long
#define maxn 1005
ll dp[maxn][maxn];
ll pass(ll a,ll b)
{
if(dp[a][b])
return dp[a][b];
if(a==b)
return 1;
if(b<a)
return 0;
return dp[a][b]=pass(a,b-1)+pass(a,b-2);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll a,b;
scanf("%lld %lld",&a,&b);
ll ans=pass(a,b);
printf("%lld\n",ans);
}
}
神考四:
#include<cstdio>
using namespace std;
#define ll long long
#define maxn 1005
ll dp[maxn][maxn];
ll pass(ll x)
{
if(x==1)
return 1;
return (pass(x-1)+1)*2;
}
int main()
{
ll t;
// scanf("%d",&t);
while(~scanf("%lld",&t))
{
// scanf("%lld",&t);
ll ans=pass(t);
printf("%lld\n",ans);
}
}