POJ3181 dp递推关系小优化 高精度数模板 Java练习

27 篇文章 0 订阅
22 篇文章 0 订阅

题意 给你n和m,问你用1...m这些数,每种无限个,相互组合,形成求和为n的方案数。

思路 dp(i,j) 表示组成求和为i,且选用的这些数最小的要>j方案数。

   转移:dp(i,j) = dp(i,j+1) + dp(i-j,j)

   注意最后数会超long long 用高精度数。


C++:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
const int maxn = 1003;
const int maxm = 102;

int n,m;

const int MAXSIZE = 100;

struct BigInt{
public:
	int a[MAXSIZE];
	int length;
public:
	BigInt():length(0){memset(a,0,sizeof(a));}
	BigInt(string s);
	BigInt(int b);
	BigInt(const BigInt& c);
	BigInt operator=(int b);
	BigInt operator=(string s);	
};



BigInt::BigInt(string s)
{
	memset(a,0,sizeof(a));
	*this = s;
}
BigInt::BigInt(int b)
{
	memset(a,0,sizeof(a));
	*this = b;
}
BigInt::BigInt(const BigInt& c)
{
	int i;
	memset(a,0,sizeof(a));	
	length = c.length;
	memset(a,0,sizeof(a));
	for(i=0;i<length;i++)
	{
		a[i] = c.a[i];
	}
}


BigInt BigInt::operator=(int b)
{
	memset(a,0,sizeof(a));
	if(b==0)
	{
		a[0] = 0;
		length = 1;
	}
	if(b<0)
	{
		b = -b;
	}
	for(length=0;b>0;length++)
	{
		a[length] = b%10;
		b /= 10;
	}
	return *this;
}

BigInt BigInt::operator=(string s)
{
	int i;
	length = s.length();
	memset(a,0,sizeof(a));
	for(i=0;i<length;i++)
	{
		a[length-i-1] = (int)(s[i] - '0');
	}
	return *this;
}


BigInt operator+(const BigInt& d,const BigInt& b)
{
	int i;
	int jinWei = 0;
	BigInt sum;
	int max_length = (d.length<b.length)?b.length:d.length;
	for(i=0;i<max_length;i++)
	{
		jinWei = d.a[i]+b.a[i]+jinWei;
		sum.a[i] = jinWei%10;
		jinWei/=10;
	}
	sum.length = i;                //sum.length 易忘赋值 
	if(jinWei!=0) 
	{
		sum.a[i] = jinWei; //加上最高位进位
		sum.length++; 
	}
	return sum;
}
BigInt operator-(const BigInt& d,const BigInt& b)   //适宜d>b时 
{
	int i,j;
	int tuiWei = 0;
	BigInt sum;
	int max_length = (d.length<b.length)?b.length:d.length;
	for(i=0;i<max_length;i++)
	{
		tuiWei = d.a[i]-b.a[i]-tuiWei;
		if(tuiWei>=0)
		{
			sum.a[i] = tuiWei;
			tuiWei = 0;
		}
		else
		{
			sum.a[i] = 10+tuiWei;
			tuiWei = 1;
		}
	}
	sum.length = i;                //sum.length 易忘赋值
	for(j=i-1;sum.a[j]==0&&j>0;j--)
		sum.length--;
	return sum;
}

BigInt operator*(const BigInt& d,const BigInt& b)
{
	int i,j,k;
	int jinWei=0;
	BigInt temp = 0;
	BigInt fuck = 0;
	if(b.a[0]==0&&b.length == 1||d.a[0]==0&&d.length == 1)
	{
		return b;
	}
	for(i=0;i<b.length;i++)   //b作为乘数 
	{
		jinWei = 0;
		temp = 0; 
		for(j=0;j<d.length;j++) //a*b[i] 
		{
			jinWei = d.a[j]*b.a[i] + jinWei;
			temp.a[j] = jinWei%10;
			jinWei /= 10;
		}
		temp.length = j;
		if(jinWei!=0)
		{
			temp.a[j] = jinWei; 
			temp.length++;
		}
	 	if(i!=0)
		{
	 		for(k=temp.length-1;k>=0;k--)  //左移i位 
	 		{
	 			temp.a[k+i] = temp.a[k];
	 			temp.a[k] = 0;
	 		}
	 		temp.length += i;
	 	}
		fuck = fuck+temp;
	}
	return fuck;
}
bool operator<(const BigInt& d,const BigInt& b)
{
	if(d.length<b.length)
		return true;
	if(d.length>b.length)
		return false;
	for(int i=b.length-1;i>=0;i--)
	{
		if(d.a[i]>b.a[i])
			return false;
		if(d.a[i]<b.a[i])
			return true;
	}
	return false;
}
bool operator==(const BigInt& d,const BigInt& b)
{
	if(d.length!=b.length)
		return false;
	for(int i=b.length-1;i>=0;i--)
	{
		if(d.a[i]!=b.a[i])
			return true;
	}
	return true;
}
bool operator!=(const BigInt& d,const BigInt& b)
{
	return !(d==b);
}
bool operator>(const BigInt& d,const BigInt& b)
{
	return !(d==b||d<b);
}
bool operator<=(const BigInt& d,const BigInt& b)
{
	return !(d>b);
}
bool operator>=(const BigInt& d,const BigInt& b)
{
	return !(d<b);
}

/
/
char* toString(BigInt a)
{
	int i;
	static char s[MAXSIZE];
	for(i=a.length-1;i>=0;i--)
	{
		s[a.length-i-1] = (char)(a.a[i]+'0');
	}
	s[a.length] =  '\0';
	return s;
}

BigInt dp[maxn][maxm];

int main()
{
	int i,j;
	while(scanf("%d%d",&n,&m) == 2)
	{
		for(i=1;i<=m;i++)
		{
			dp[0][i] = 1;
		}
		for(i=1;i<=n;i++)
		{
			for(j=min(m,i);j>=1;j--)
			{
				dp[i][j] = dp[i][j+1] + dp[i-j][j];
			}
		}
		char* tmp = toString(dp[n][1]);
		printf("%s\n",tmp);
	}
	return 0;
}



Java

import java.util.*;
import java.math.*;

public class Main{
	static final int maxn = 1003;
	static final int maxm = 102;
	static BigInteger[][] dp = new  BigInteger[maxn][maxm];
	static Scanner cin = new Scanner(System.in);
	static public void main(String args[]){
		
		int n,m;
		while(cin.hasNextInt() == true)
		{
			n = cin.nextInt();
			m = cin.nextInt();
			int i = 0,j = 0;

			for(i = 1;i<=m;i++)
				dp[0][i] = BigInteger.ONE;
			for(i=1;i<=n;i++)
			{
				for(j=Math.min(i,m);j>=1;j--)
				{
					if(dp[i][j+1] == null)
						dp[i][j+1] = BigInteger.ZERO;
					if(dp[i-j][j] == null)
						dp[i-j][j] = BigInteger.ZERO;
					dp[i][j] = BigInteger.ZERO;
					dp[i][j] = dp[i][j+1].add(dp[i-j][j]);
				}
			}
			
			System.out.println(dp[n][1].toString());
		}
	}
	
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值