描述
A sequence of positive integers is Palindromic if it reads the same forward and backward. For example:
23 11 15 1 37 37 1 15 11 23
1 1 2 3 4 7 7 10 7 7 4 3 2 1 1
A Palindromic sequence is Unimodal Palindromic if the values do not decrease up to the middle value and then (since the sequence is palindromic) do not increase from the middle to the end For example, the first example sequence above is NOT Unimodal Palindromic while the second example is.
A Unimodal Palindromic sequence is a Unimodal Palindromic Decomposition of an integer N, if the sum of the integers in the sequence is N. For example, all of the Unimodal Palindromic Decompositions of the first few integers are given below:
1: (1)
2: (2), (1 1)
3: (3), (1 1 1)
4: (4), (1 2 1), (2 2), (1 1 1 1)
5: (5), (1 3 1), (1 1 1 1 1)
6: (6), (1 4 1), (2 2 2), (1 1 2 1 1), (3 3),
(1 2 2 1), ( 1 1 1 1 1 1)
7: (7), (1 5 1), (2 3 2), (1 1 3 1 1), (1 1 1 1 1 1 1)
8: (8), (1 6 1), (2 4 2), (1 1 4 1 1), (1 2 2 2 1),
(1 1 1 2 1 1 1), ( 4 4), (1 3 3 1), (2 2 2 2),
(1 1 2 2 1 1), (1 1 1 1 1 1 1 1)
Write a program, which computes the number of Unimodal Palindromic Decompositions of an integer.
输入
Input consists of a sequence of positive integers, one per line ending with a 0 (zero) indicating the end.
输出
For each input value except the last, the output is a line containing the input value followed by a space, then the number of Unimodal Palindromic Decompositions of the input value. See the example on the next page.
样例输入
2 3 4 5 6 7 8 10 23 24 131 213 92 0
样例输出
2 2 3 2 4 4 5 3 6 7 7 5 8 11 10 17 23 104 24 199 131 5010688 213 1055852590 92 331143
提示
N < 250
解题分析
经典的动态规划题目,也借此引出一个思想,就是动态规划的过程中,如果觉得问题难以描述或者难以用子问题解决,也许是需要更多的信息了,所以不妨多加上几个维度。比如此题,一开始笔者妄图用一维dp数组去解,最后惨败下风。所以后面自己加了一个维度,dp[i][j]代表,对于数字i的UPD分解,两边上的数字为j的时候,分解的数量,并且这个分解是满足中间为最高(对于偶数个情况下中间可以是两个大小一样的数字,比如4分解为(2,2)),然后考虑一个特殊的情况就是数字的自我单独分解,也就是比如4分解为(4),这个我们定义为dp[i][0],好吧,就是单独一个的,我们拎出来说明白。然后,考虑一下我们怎么去更新我们的dp数组,然后,分析一下,我们很容易就明白了,我们旁边的数不可能超过i/2,因为i/2 * 2 = i。dp[i][j]=(dp[i-2*j][0]+dp[i-2*j][1]+...+dp[i-2*j][k]); k=j的情况下,我们可以说dp[i][j]+=dp[i-2*j][0],确保k>=j的情况下,我们用一个循环去累加。
代码实现
#include <iostream>
#include <cmath>
//#include <iomanip>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <bitset>
#include <queue>
#include <stack>
#include <cstdlib>
using namespace std;
int N;
long long dp[255][130]={0};
int main(){
while(scanf("%d",&N)!=EOF){
if(N==0) break;
dp[1][0]=1;
dp[2][0]=1;
dp[2][1]=1;
//dp[i][j]=dp[i-2*j][0]+dp[i-2*j][k];
for(int i=3;i<=N;i++){
if(dp[i][0]) continue;
dp[i][0]=1;
for(int j=1;j<=i/2;j++){
if(i-2*j>=j){
dp[i][j]+=dp[i-2*j][0];
}
for(int k=j;k<=(i-2*j)/2;k++){
dp[i][j]+=dp[i-2*j][k];
}
if(i%2==0) dp[i][i/2]=1;
}
}
long long ans=0;
for(int i=0;i<=N/2;i++){
ans+=dp[N][i];
}
printf("%d %lld\n",N,ans);
}
return 0;
}