1011. Lenny's Lucky Lotto
题目大意:
给定正整数n, m,构建的列表满足下列条件:
- 列表长度为n
- 列表的第i个数不能超过2的i次方
- 列表的最后一个数不能超过m
求出这样的列表的最大数目。
解题思路:
- 一般遇到需要求最优解的,应该立马想到动态规划;
- 影响列表的数目的应该是有两个状态,一个是列表的长度,一个是列表的末尾值。因此采用两个状态,申请表dp[11][2001]。其中dp[i][j]表示:当长度为i,末尾为j的列表的数目。
- 状态转移方程:
dp[i][j] = dp[i][j-1] + dp[i-1][j/2]
很容易理解这个状态方程。
初始化状态当然是dp[1][i] = i,加上一些必要的剪支,列表的第i个数一定是大于2的i次方并且要小于(m / 2^(n-i))的,自己可以证明。
一开始疏忽了,没有使用long long类型,WA几次之后发现数字过大时,可能出现负数,使用printf打印long long时是采用%lld的格式。
原题目见底下附带。
代码如下:
/*
* main.cpp
*
* Created on: Sep 23, 2011
* Author: raphealguo( rapheal.iteye.com)
*/
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#define N 11
#define M 2001
long long dp[N][M];//dp[i][j] 表示n=i m=j时的最大Luck list数目
int n, m;
void solve(){
//动态规划
int i, j;
for (i = 1; i <= m; ++i){//初始化
dp[1][i] = i;
}
for (i = 2; i <= n; ++i){
for (j = 1<<(i-1); j*(1<<(n-i)) <= m; ++j){//必要作出一些剪支,减少运算
dp[i][j] = dp[i][j-1] + dp[i-1][j/2];
}
}
}
int main(){
int t, c = 1;
scanf ("%d", &t);
while (t--){
memset(dp, 0, sizeof(dp));
scanf ("%d %d", &n, &m);
solve();
printf("Case %d: n = %d, m = %d, # lists = %lld\n", c++, n, m, dp[n][m]);
}
return 0;
}
附带原题目:
1011. Lenny's Lucky Lotto
Description
Lenny likes to play the game of lotto. In the lotto game, he picks a list of
N
unique numbers in the range from
1
to
M
. If his list matches the list of numbers that are drawn, he wins the big prize.
Lenny has a scheme that he thinks is likely to be lucky. He likes to choose his list so that each number in it is at least twice as large as the one before it. So, for example, if
N
= 4
and
M
= 10
, then the possible lucky lists Lenny could like are:
1 2 4 8
1 2 4 9
1 2 4 10
1 2 5 10
Thus Lenny has four lists from which to choose.
Your job, given
N
and
M
, is to determine from how many lucky lists Lenny can choose.
Input
There will be multiple cases to consider from input. The first input will be a number C (0 < C <= 50) indicating how many cases with which you will deal. Following this number will be pairs of integers giving values for N and M, in that order. You are guaranteed that 1 <= N <= 10, 1 <= M <= 2000, and N <= M. Each N M pair will occur on a line of its own. N and M will be separated by a single space.
Output
For each case display a line containing the case number (starting with 1 and increasing sequentially), the input values for N and M, and the number of lucky lists meeting Lenny’s requirements. The desired format is illustrated in the sample shown below.
Sample Input
3
4 10
2 20
2 200
Sample Output
Case 1: n = 4, m = 10, # lists = 4
Case 2: n = 2, m = 20, # lists = 100
Case 3: n = 2, m = 200, # lists = 10000
分享到:
相关推荐
sicily部分源代码,全都亲测,可通过
中大sicily online judge的刷题指南,里面介绍得很详细,不过,最近sicily好像不能外网访问了。
sicily 1562_LVM.cpp参考代码
112页的大礼包,sicily的部分ac代码。
本cpp是sicily的1006的解题代码 这份代码以最简单的方式实现了它的功能要求 值得学习一番
Sicily的题目分类:各种题目的分类,大致方法,以及题目难度规范
sicily1007题答案,附代码解释,可以在平台上通过
sicily 1274的AC源码,通过且速度快,适合学生使用
对于二叉树T,可以递归定义它的先序遍历、中序遍历和后序遍历如下: PreOrder(T)=T的根节点+PreOrder(T的左子树)+PreOrder(T的右子树) InOrder(T)=InOrder(T的左子树)+T的根节点+InOrder(T的右子树) PostOrder(T)=...
中山大学 ACM sicily 1294 题目代码
本程序解决了Sicily平台上Queue的问题,有较好的可读性
sicily(soj) 1022 1064 1310 1740 1876 1934 六题的源代码(数据结构综合应用题)
sicily 1817和1818的程序,各有两种方法,供参考。
本程序是中山大学sicily 1004-1007-1010-1014-1021 参考代码
本程序是中山大学sicily-1137-1145-1146-1147-1154-1157-1194的代码
本程序是中山大学sicily上1200-1221-1298-1324-1325的参考代码。
包括 sicily online judge 1149等部分题目,线性表,最小生成树,中缀转后缀并计算后缀表达式等。
此处是sicily 1093,1888 c++的源代码
Sicily Online Judge,原题代码