POJ 1221 UNIMODAL PALINDROMIC DECOMPOSITIONS

UNIMODAL PALINDROMIC DECOMPOSITIONS
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 4534 Accepted: 2224

Description

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

Input consists of a sequence of positive integers, one per line ending with a 0 (zero) indicating the end.

Output

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.

Sample Input

2
3
4
5
6
7
8
10
23
24
131
213
92
0

Sample Output

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

Source

 
题意:
求和为n的单峰回文序列的个数
 
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#define MAX 302
using namespace std;

__int64 num[MAX][MAX];    //注意最后输出的结果会超int
						  //num[i][j]用来存储和为i且序列中所有数都不超过j的回文序列的个数

int main()
{
	int n,i,j;
	
	memset(num,0,sizeof(0));
	for(i=0;i<MAX;i++)
		for(j=0;j<MAX;j++)
			if(i==0 || i>=j) num[i][j]=1;
	for(i=1;i<MAX;i++)
		for(j=i/2;j>=1;j--)
			num[i][j]=num[i-2*j][j]+num[i][j+1];
	while(scanf("%d",&n)!=EOF &&n!=0)
	{
		printf("%d %I64d\n",n,num[n][1]);    //注意输出格式
	}
	return 0;
}

思路:
×先研究一下每一组数据时怎样由前面的推出的。比如 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个。
  1、6=1+1+4。那么他可以将4的所有情况两边都加1变成6的解 (1 4 1), (1 1 2 1 1), (1 2 2 1), ( 1 1 1 1 1 1)共4个。
  2、6=2+2+2。那么他可以将2的所有最小值大于等于2的情况两边加2 即将(2) 变成 (2,2,2) 共1个
  3、6=3+3+0。注意只有另一个数是0的时候才可以这么拆 如 5= 2+2+1 是不可以的。那么他可以将0 的所有情况两边加3,变成3,3 共1个。这里默认0的情况总数是1。
  4、6本身自己 (6) 就是一组 共1个所以 6的解共4+1+1+1=7个。
×由上面得状态转移方程:num[i][j]=num[i-2*j][j]+num[i][j+1];(num[i][j]用来存储和为i且序列中所有数都不超过j的回文序列的个数)
×数组的初始化:
  1、将s[i][j] (i>=j>i/2) 内容预处理成1(因为对于j>i/2时 所有的s[i][j]都是1,如s[6][4]=s[6][5]=s[6][6]=1 只有(6)一个)
  2、将s[i][j] (i<j) 内容预处理成0 (因为根据定义j不可能比i大)
  3、将s[0][j] 内容预处理成1 (因为当需要调用s[0][j]时表示一个数拆成了完全相同的两个数,结果当然是一个)
×具体实现:
  在for (i=2;i<=max;i++)的每次循环中加入for (j=i/2;j>=1;j--)循环,每次逆推结果程序实现过程
  比如:i=6时:1、j=3 s[6][3] = s[6-3*2][3] + s[6][4] = 1 + 1 =2 ; 表示6中解大于3的有两种(3,3),(6);
                            2、j=2 s[6][2] = s[2][2] + s[6][3] = 1 + 2 =3;
                            3、j=1 s[6][1] = s[4][1] + s[6][2] = 4 + 3 =7; s[6][1]中储存n=6时的所有解。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值