POJ3181--Dollar Dayz
2015-08-25 00:14
274 查看
题目大意:给出两个整数n,m,求m以内的整数组成n有多少种情况
分析:这题数据超大,使用了将大数分开处理的方法。参考了别人的分析http://blog.csdn.net/libin56842/article/details/9455979。接下来,先介绍一下整数划分的问题。
所谓整数划分,是把一个整数N拆分成一组数相加并且等于N的问题。
例如:
6
5+1
4+2,4+1+1
3+3,3+2+1,3+1+1+1
2+2+2,2+2+1+1,2+1+1+1+1
1+1+1+1+1+1
假设F(N, M)表示划分个数,M表示将N拆分后的序列中最大不超过M
考虑边界状态:
N=1或者M=1都只有一种方法,即F(1, 1) = 1
M=N时,等于最大数为M-1时加上1(就是N本身),F(N, N) = F(N, N-1)+1
M>N时,最大数比N大就没有意义了,所以,F(N, M) = F(N, N)
M<N时,等于序列中最大数为M-1的划分和N-M的划分之和,例如,F(6, 4)等于对3的划分,加上2的划分。F(N, M) = F(N, M-1) + F(N-M, M)
状态:dp[i][j]表示整数i最大数不超过j的划分个数
状态转移方程为:dp[i][j] = dp[i][j-1]+dp[i-j][j]
代码:
#include <cstdio>
#include <cstring>
using namespace std;
long long dp[1111][111][2];
#define INF 100000000000000000
int main() {
int n, k;
scanf("%d%d", &n, &k);
memset(dp, 0, sizeof(dp));
for(int i = 0; i <= k; i++)
dp[0][i][1] = 1;
for(int j = 1; j <= k; j++) {
for(int i = 1; i <= n; i++) {
if(i < j) {
dp[i][j][0] = dp[i][j-1][0];
dp[i][j][1] = dp[i][j-1][1];
}
else {
dp[i][j][0] = dp[i][j-1][0]+dp[i-j][j][0];
dp[i][j][1] = dp[i][j-1][1]+dp[i-j][j][1];
dp[i][j][0] += dp[i][j][1]/INF; //大数的高位
dp[i][j][1] = dp[i][j][1]%INF; //大数的低位
}
}
}
if(dp
[k][0]) printf("%lld", dp
[k][0]);
printf("%lld\n", dp
[k][1]);
return 0;
}
分析:这题数据超大,使用了将大数分开处理的方法。参考了别人的分析http://blog.csdn.net/libin56842/article/details/9455979。接下来,先介绍一下整数划分的问题。
所谓整数划分,是把一个整数N拆分成一组数相加并且等于N的问题。
例如:
6
5+1
4+2,4+1+1
3+3,3+2+1,3+1+1+1
2+2+2,2+2+1+1,2+1+1+1+1
1+1+1+1+1+1
假设F(N, M)表示划分个数,M表示将N拆分后的序列中最大不超过M
考虑边界状态:
N=1或者M=1都只有一种方法,即F(1, 1) = 1
M=N时,等于最大数为M-1时加上1(就是N本身),F(N, N) = F(N, N-1)+1
M>N时,最大数比N大就没有意义了,所以,F(N, M) = F(N, N)
M<N时,等于序列中最大数为M-1的划分和N-M的划分之和,例如,F(6, 4)等于对3的划分,加上2的划分。F(N, M) = F(N, M-1) + F(N-M, M)
状态:dp[i][j]表示整数i最大数不超过j的划分个数
状态转移方程为:dp[i][j] = dp[i][j-1]+dp[i-j][j]
代码:
#include <cstdio>
#include <cstring>
using namespace std;
long long dp[1111][111][2];
#define INF 100000000000000000
int main() {
int n, k;
scanf("%d%d", &n, &k);
memset(dp, 0, sizeof(dp));
for(int i = 0; i <= k; i++)
dp[0][i][1] = 1;
for(int j = 1; j <= k; j++) {
for(int i = 1; i <= n; i++) {
if(i < j) {
dp[i][j][0] = dp[i][j-1][0];
dp[i][j][1] = dp[i][j-1][1];
}
else {
dp[i][j][0] = dp[i][j-1][0]+dp[i-j][j][0];
dp[i][j][1] = dp[i][j-1][1]+dp[i-j][j][1];
dp[i][j][0] += dp[i][j][1]/INF; //大数的高位
dp[i][j][1] = dp[i][j][1]%INF; //大数的低位
}
}
}
if(dp
[k][0]) printf("%lld", dp
[k][0]);
printf("%lld\n", dp
[k][1]);
return 0;
}
相关文章推荐
- phpstorm通过ftp远程开发服务器上的项目
- JavaScript设置自适应居中
- android ble 4.0实现自动配对
- 链表
- 用命令行(CMD)中启动和关闭ORACLE服务
- UVA 11427 Expect the Expected (概率dp+推公式求期望 详解)
- Java泛型总结(转)
- UDP通信(Red Hat Enterprise Linux 6)
- Opencv + Qt 获取视频中任意一帧
- UVA - 11613 Acme Corporation(最小费用流)
- display:table的几个妙用:垂直居中、浮动……
- cocos2d-x中CCSprite更换图片
- LeetCode Ugly Number
- Java 类加载机制 ClassLoder
- Java 类加载机制 ClassLoder
- [笔记]软件体系结构(2)--分层
- Java 类加载机制 ClassLoder
- 今天开始正式进军汽配行业,赚钱钱,明年买新款吉姆尼了哟............动力动力!再有钱了换牧马人哈哈哈哈
- docker学习笔记1—常用命令
- 机试题 最高分是多少-链表