POJ 3181 dp

题意

传送门 POJ 3181

基本思路

d p [ i ] [ j ] = n 0 , j k n 0 d p [ i 1 ] [ j k n ] dp[i][j]=\sum_{n\geq0,j-k*n\geq0}dp[i-1][j-k*n]

优化递推式

d p [ i ] [ j ] = d p [ i ] [ j k ] + d p [ i 1 ] [ j ] dp[i][j]=dp[i][j-k]+dp[i-1][j]

结果 l o n g   l o n g long\ long 也会溢出,实现上使用大数运算。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f
#define delta 0.85
#define eps 1e-3
#define PI 3.14159265358979323846
#define MAX_L 40
#define MAX_K 105
#define MAX_N 1005
using namespace std;
struct bignum{
	int limit;
	int s[MAX_L];
	bignum(){limit = 0; for(int i = 0; i < MAX_L; i++) s[i] = 0;}
	void operator = (const bignum& other){
		limit = other.limit;
		for(int i = 0; i < MAX_L; i++) s[i] = other.s[i];
	}
	void operator += (const bignum& other){
		int p = max(limit, other.limit);
		for(int i = 0; i < p; i++){
			s[i] += other.s[i];
			if(s[i] >= 10) s[i] -= 10, s[i + 1]++;
		}
		limit = s[p] > 0 ? p + 1 : p;
	}
	void output(){
		for(int i = limit - 1; i >= 0; i--) putchar(s[i] + '0');
		putchar('\n');
	}
}dp[MAX_K][MAX_N];
int N, K;

int main(){
	dp[0][0].s[0] = dp[0][0].limit = 1;
	for(int i = 1; i < MAX_K; i++){
		for(int j = 0; j < MAX_N; j++){
			dp[i][j] = dp[i - 1][j];
			if(j >= i) dp[i][j] += dp[i][j - i];
		}
	}
	while(~scanf("%d%d", &N, &K)){
		dp[K][N].output();
	}
	return 0;
}
发布了91 篇原创文章 · 获赞 1 · 访问量 1615

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/105151476