Time Limit: 1 second

Memory Limit: 128 MB

【问题描述】

最近Kfc新开了个KFC,该KFC提供N种食物,分别用1-N给这些食物编号,食物的价格与其编号有关,满足第K种食物的价格为2^(K-1),例如

: 食物的编号 1 2 3 4 5 6 7 8 9 10……

价格 1 2 4 8 16 32 64 128 256 512 ……

每位顾客最多可以选择L种食物,且每种食物仅一份。

当顾客选择食物时,他会说:我要第M便宜的食物组合。

Kfc的工作就是计算第该食物组合的价格。

一样食物都不要也是一种组合,因此第1便宜的食物组合价格为0。

【输入格式】

一行,包含三个整数N (1<=N<=30),,L (1<=L<=N),M,用一个空格隔开。数据保证存在第M便宜的食品组合。

【输出格式】

一行,包含一个整数P,P为第M便宜的食品组合的价格。

【数据规模】

Sample Input1

5 3 19

Sample Output1

19

【题解】

先宣泄一下:这题真TM****.

然后是思路。

很明显。2^(i-1)。和二进制有关。

然后。如果你一开始一个一个去累加。要加很多次。然后会超时5个点左右。(有分!我宁愿只要50分)

所以我们用排列组合去做。

比如我们想知道最高位的1要放在哪里。

比如放在i;

sum[i] += C[i-1][0..l-1]

这边的组合数就表示在前i-1个0当中选出0..l-1(因为第i位放了一个1所以只剩l-1个)个1

然后sum[i] = sum[i] + sum[i-1];

我们则要找到一个i

满足sum[i] <= m <sum[i+1];(如果sum[i] == m则只要在i-l+1..i这些位置上置1就可以了。然后直接输出答案不用继续搜索)

然后若是m>sum[i],则记录这个i停止break掉i的循环。

然后a[i+1]=1,表示在i+1这个位置放一个1;

然后对于00...001(这里的1是第i+1)位。

我们要在1的前面再加上几个1.以达到修改后的数字字典序是第m-sum[i]的目的;

可以发现这是一个递归的过程

直接执行solve(i,l-1,m-sum[i]);

表示在1..i中找到一个合适的最高位,可以放的1的数目为l-1(因为已经放了一个1所以可选食品减少了1);

然后变成求倒数第m-sum[i]便宜的物品组合了。

【代码】

#include <cstdio>

int n, l, m, a[35] = { 0 }, two_n[32];
int c[35][35] = { 0 };
int sum[31] = { 0 };
bool done = false; int min(int a, int b) //返回a和b中的较小值。
{
return a > b ? b : a;
} void input_data() //输入数据
{
scanf("%d%d%d", &n, &l, &m);
} void init() //用杨辉三角和组合数对应的关系递推出组合数
{
for (int i = 0; i <= 30; i++)
c[i][0] = 1, c[i][i] = 1;
for (int i = 1; i <= 30; i++)
for (int j = 1; j <= i; j++)
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
} void output_ans() //输出答案
{
two_n[0] = 1;
for (int i = 1; i <= 31; i++)
two_n[i] = two_n[i - 1] * 2; //预处理出2^n
int sum = 0;
for (int i = 1; i <= 30; i++) //按照2进制转10进制的方法获取答案
sum += (two_n[i - 1] * a[i]);
printf("%d\n", sum);
} void solve(int nn, int ll, int mm) //在1..nn中找一个合适的最高位放下一个1,然后可以选的食品数目为ll
{//要找的是第mm便宜的。。
int n = nn, l = ll, m = mm, pos1 = 0;
sum[0] = 1; //要注意什么都不选也是一种组合。
for (int i = 1; i <= n; i++) //最高位在第i位
{ //接下来枚举前i-1个空位放几个1(在i-1和l-1之间求一个最小值作为上限)
sum[i] = 0;
for (int j = 0; j <= min(i - 1, l - 1); j++)
sum[i] += c[i - 1][j];
sum[i] += sum[i - 1]; //表示1放在i会有多少种组合。
}
for (int i = 0; i <= n; i++)
if (sum[i] == m) //如果恰好为所需要的
{
int begin = i - l + 1; //00..01(1在第i位)。在i-l+1到i这段区间内。全部赋值为1.
if (begin < 1) //这是在前i个位置放置L个1的所有方案中最贵的。也就是我们所需要的。
begin = 1; //如果小于1了 (注意是有l种食品可以选 但没说全要选!);
for (int j = begin; j <= i; j++)
a[j] = 1;
m -= sum[i]; //直接减掉。当然不减也没事
done = true;//这个东西没用。
return;//直接退出递归。然后就会输出答案了。
}
else if (sum[i] < m && sum[i + 1] >m) //如果找到一个放1的合适位置
{
pos1 = i + 1; //记录放1的位置
m -= sum[i]; //减去前i个位置放L个1的方案数。接下来在第i+1个位置放一个1
break; //然后递归求前i个位置放L-1个物品的方案数,所求字典序变成m-sum[i]。
}
if (pos1 != 0) //把1放置 其实是一定能够找到这样一个pos1的。
a[pos1] = 1;
if (l == 1) //这是递归的边界。我不会跟你讲这个是可以去掉的。
return;
if (pos1 == 1)
return;
solve(pos1 - 1, l - 1, m);//递归求前i个位置放置l-1个1,然后m已经减去sum[i]了。
} int main()
{
init();
input_data();
solve(n, l, m);
output_ans();
return 0;
}

【u210】kfc的更多相关文章

  1. 【NOIP2014】伤感·伤感·伤感

    Day <0 虽说初三的时候考过一次提高组,而且还考得不错,但自己还是挺看重这次NOIP的[你想想旁边两大神级别人物在死命刷题,蒟蒻怎敢颓废]于是切完所有复赛题后又做了好多好多次模拟赛,状态自己 ...

  2. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  3. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  4. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  6. 【调侃】IOC前世今生

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

  7. Python高手之路【三】python基础之函数

    基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...

  8. Python高手之路【一】初识python

    Python简介 1:Python的创始人 Python (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种解释型.面向对象.动态数据类型的高级程序设计语言,由荷兰人Guido ...

  9. 【开源】简单4步搞定QQ登录,无需什么代码功底【无语言界限】

    说17号发超简单的教程就17号,qq核审通过后就封装了这个,现在放出来~~ 这个是我封装的一个开源项目:https://github.com/dunitian/LoTQQLogin ————————— ...

随机推荐

  1. SSO单点登录学习总结(1)——单点登录(SSO)原理解析

    SSO的概念: 单点登录SSO(Single Sign-On)是身份管理中的一部分.SSO的一种较为通俗的定义是:SSO是指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应 ...

  2. [CortexM0--stm32f0308]discovery开发板

        问题描写叙述:stm32提供了很多IC入门级开发板,价格还是蛮廉价的. stm32f0308-discovery就是一款cortex-m0架构的入门级开发板. 例如以下对其进行下简介. IO便 ...

  3. silverlight依据json字符串动态创建实体类

    1.接收json字符串: //用JsonValue转换json字符串是为了之后获得json字符串的每行数据和每一列的列名 JsonValue jv = JsonValue.Parse(json);   ...

  4. How to Rotate Tomcat catalina.out

    If catalina.out becomes 2GB in size, tomcat crashes and fails to start without any error message. To ...

  5. GO语言学习(九)Go 语言运算符

    运算符用于在程序运行时执行数学或逻辑运算. Go 语言内置的运算符有: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 接下来让我们来详细看看各个运算符的介绍. 算术运算符 下表 ...

  6. 设计模式--单例模式之Lock

    1.为什么用Lock及关键知识 当我们使用线程的时候,效率最高的方式当然是异步,即个个线程同时运行,其间互不依赖和等待.当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进 ...

  7. struts2笔记---struts2的执行过程

    1.服务器启动: 加载项目web.xml 创建struts核心过滤器对象,执行filter-->init() struts-default.xml     核心功能的初始化 struts-plu ...

  8. poj 3100 (zoj 2818)||ZOJ 2829 ||ZOJ 1938 (poj 2249)

    水题三题: 1.给你B和N,求个整数A使得A^n最接近B 2. 输出第N个能被3或者5整除的数 3.给你整数n和k,让你求组合数c(n,k) 1.poj 3100 (zoj 2818) Root of ...

  9. 【习题 3-4 UVA - 455】Periodic Strings

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举 [代码] #include <bits/stdc++.h> using namespace std; const ...

  10. 解决安装mysql-connector-odbc-5.3.2 错误1918……不能载入安装或转换器库……的BUG

    还是在虚拟机Windows Server 2003上安装mysql-connector-odbc-5.3.2,装着装着就报错了,大致是"错误1918--不能载入安装或转换器库--" ...