题意很简单,给你一个正整数数n,将n拆分成一个正整数数字序列,要求数字序列和为n且是个回文并且左半部分的序列非降。问n拆分成这样的序列有几种方案?
设d(n,k)表示n左右两边是k的时候的方案数(注意n不包含k),那么递推式:
表示当前这一种方案(n,k)加上方案(n-2i,i)的方案数,注意一下边界。
本题其实就是一个递推式,由于用到了记忆化所以就写得跟dp一样了。。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn=500;
LL d[maxn+5][maxn+5];
LL dp(int n,int k){
if(n==0||k==0)return 1;
if(n==k)return 1;
if(n<k)return 0;
LL &ans=d[n][k];
if(ans)return ans;
ans=1;
for(int i=k;i<=n;i++){
ans+=dp(n-2*i,i);
}
return ans;
}
int main(){
int n;
memset(d,0,sizeof(d));//在外面将d清空一次即可,放在while循环中会重复计算
while(~scanf("%d",&n),n){
LL ans=0;
for(int i=0;i<=n;i++){
ans+=dp(n-2*i,i);
}
printf("%d %lld\n",n,ans);
}
}