题目链接

题目大意

使用10、20、50、100元面额的硬币能分别组成题目给出的面额,需要最少的硬币个数

分析

一开始队友想用一堆if-else解决问题,然后WA了无数发……

我想到了一种比较简单的打表法来解决这个问题,而这个表长度只有13个int

在开始分析之前,我们先不考虑出现 -1 的解。即出现某种情况 mod 10不等于0,因为这个判断非常简单

定律

开始推这个表之前先确定一个显而易见的定律

若存在两种方案的需要的硬币数一样,且第一种的方案能组成的面额第二种都可以组成,则第一种方案不可取。

证明:如果我使用了第一组方案,则我必定可以使用第二种方案,即使第二种方案不能组成其他更多的面额,这样的选择也是完全没有错误的

推论

根据定律,可以得到下面这些推论

1、不存在一种方案包含两个10元、同理有两个50元也不存在

证明:如果存在一个方案包含两个10元,则我们可以选择用一个10元和一个20元代替这个方案。我们可以确定,两个10元只能组成10、20这两个面额。而10元和20元可以组成10元、20元、30元三个面额。根据定律,则确定此方案不可行。同理,两个50元可以用50+100代替

2、仅使用4个非100元的硬币,只有两种组成方案:10、20、20、50和20、20、20、50

证明:对于4个硬币,方案10、20、20、50可以组成10-100的所有情况,所以任何其他方案如果合理,则必须能组成有超过100元的情况。根据推论1,则50元不可以重复,所以能组成的最大的值就是用20、20、20、50组成110。

3、不存在使用5个非100元的硬币的情况

证明:首先如果使用了5个硬币,根据推论1,可以得到的组合仅两种:10、20、20、20、50即120元,和20、20、20、20、50即130元。那么无论这个组合怎么样,通过推论2的结论,都不如10、20、20、50、100这个组合,因为这个组合能完成10-200以内的所有解。那么根据定律,上述两个组合都是错误的组合。

4、大于110元的面额必须要通过一个或者数个100元的硬币来组成

证明:这个很简单,通过推理3可以直接推出。所以对于大于110元的面额都应不断的-100直到满足上述情况

打表

那么我们知道了最多只有4个非100元的硬币,那么我们就可以得到所有的组合情况(省略0)

1

2

5

1 2

1 5

2 2

2 5

1 2 2

1 2 5

2 2 2

2 2 5

1 2 2 5

2 2 2 5

那么我们可以把这些情况能组成的数字打表出来

1

2

5

1 2 3

1 5 6

2 4

2 5 7

1 2 3 4 5

1 2 3 5 6 7 8

2 4 6

2 4 5 7 9

1 2 3 4 5 6 7 8 9 10

2 4 6 7 9 11

借助位运算,我们可以这样做:

print(1 << 1)
print(1 << 2)
print(1 << 5)
print((1 << 1) + (1 << 2) + (1 << 3))
print((1 << 1) + (1 << 5) + (1 << 6))
print((1 << 2) + (1 << 4))
print((1 << 2) + (1 << 5) + (1 << 7))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 8))
print((1 << 2) + (1 << 4) + (1 << 6))
print((1 << 2) + (1 << 4) + (1 << 5) + (1 << 7) + (1 << 9))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 8) + (1 << 9) + (1 << 10))
print((1 << 2) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 9) + (1 << 11))

可以尝试理解这个表的原理,即将每一个bite作为表的一个元素

可以看到最大值只有110元。而注意到面额最大的硬币为100。而110元可以用非100元组成也可以通过10元+100元组成,同理100元也有两种组合方式。所以需要考虑四个情况:

1、100元用100元组成、110元用100元组成

2、100元用100元组成、110元用非100元组成

3、100元用非100元组成、110元用100元组成

4、100元用非100元组成、110元用非100元组成

那么都考虑一下,取较小者

AC-Code

#include<bits/stdc++.h>

using namespace std;

vector<int> res;

void init() {
res.push_back(0);
res.push_back(2);
res.push_back(4);
res.push_back(32);
res.push_back(14);
res.push_back(98);
res.push_back(20);
res.push_back(164);
res.push_back(62);
res.push_back(494);
res.push_back(84);
res.push_back(692);
res.push_back(2046);
res.push_back(2804);
} int get_ans(int as) {
int t = -1;
for (int i = 0; i < res.size(); ++i) {
if ((res[i] ^ as) + (res[i] & as) == res[i]) {
t = i;
break;
}
}
switch (t) {
case 0:
return 0;
case 1:
case 2:
case 3:
return 1;
case 4:
case 5:
case 6:
case 7:
return 2;
case 8:
case 9:
case 10:
case 11:
return 3;
case 12:
case 13:
return 4;
}
return 1000;
} int main() {
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto start_clock_for_debug = clock();
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cin.tie(0); int t;
cin >> t;
init();
while (t--) {
int n;
cin >> n; int hun[4];
int cnt[4][15];
memset(cnt, 0, sizeof(cnt));
memset(hun, 0, sizeof(hun));
bool flag = false; for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp; if (flag) continue; if (tmp % 10) {
flag = true;
continue;
}
// 100 + 110
int tmp0 = tmp;
if (tmp0 % 100 > 10 and tmp0 > 100) {
hun[0] = max(tmp0 / 100, hun[0]);
tmp0 %= 100;
cnt[0][tmp0 / 10]++;
} else if (tmp0 > 100) {
hun[0] = max((tmp0 - 100) / 100, hun[0]);
tmp0 %= 100;
cnt[0][tmp0 / 10 + 10]++;
} else {
cnt[0][tmp0 / 10]++;
}
// 100
int tmp1 = tmp;
if (tmp1 % 100 == 0 and tmp1 > 100) {
hun[1] = max((tmp1 - 100) / 100, hun[1]);
cnt[1][10]++;
} else {
hun[1] = max(tmp1 / 100, hun[1]);
cnt[1][(tmp1 % 100) / 10]++;
}
// 110
int tmp2 = tmp;
if (tmp2 % 100 == 10 and tmp2 > 100) {
hun[2] = max((tmp2 - 100) / 100, hun[2]);
cnt[2][11]++;
} else {
hun[2] = max(tmp2 / 100, hun[2]);
cnt[2][(tmp2 % 100) / 10]++;
}
// None
int tmp3 = tmp;
hun[3] = max(tmp3 / 100, hun[3]);
cnt[3][(tmp3 % 100) / 10]++;
}
if (flag) {
cout << -1 << endl;
continue;
}
int ans;
int get_ans[4]; for (int j = 0; j < 4; ++j) {
ans = 0;
for (int k = 1; k < 13; ++k) {
if (cnt[j][k]) {
ans += 1 << k;
}
}
get_ans[j] = get_ans(ans) + hun[j];
}
sort(get_ans, get_ans + 4);
cout << get_ans[0] << endl;
}
#ifdef ACM_LOCAL
auto end_clock_for_debug = clock();
cerr << "Run Time: " << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
#endif
return 0;
}

【2019HDU多校】第九场1006/HDU6685-Rikka with Coin——位运算打表的更多相关文章

  1. hdu多校第九场 1006 (hdu6685) Rikka with Coin 暴力

    题意: 有一些1毛,2毛,5毛,1块的钢镚,还有一些价格不同的商品,现在要求你带一些钢镚,以保证这些商品中任选一件都能正好用这些钢镚付账,问最少带多少钢镚. 题解: 对于最优解,1毛的钢镚最多带1个, ...

  2. 2019HDU多校第九场 Rikka with Quicksort —— 数学推导&&分段打表

    题意 设 $$g_m(n)=\begin{cases}& g_m(i) = 0,     \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ...

  3. HDU 4691(多校第九场1006) 后缀数组

    ...还能多说什么. 眼角一滴翔滑过. 一直以为题意是当前串与所有之前输入的串的LCP...然后就T了一整场. 扫了一眼标程突然发现他只比较输入的串和上一个串? 我心中突然有千万匹草泥马踏过. 然后随 ...

  4. 2019HDU多校第一场1001 BLANK (DP)(HDU6578)

    2019HDU多校第一场1001 BLANK (DP) 题意:构造一个长度为n(n<=10)的序列,其中的值域为{0,1,2,3}存在m个限制条件,表示为 l r x意义为[L,R]区间里最多能 ...

  5. 2018 Multi-University Training Contest 9 杭电多校第九场 (有坑待补)

    咕咕咕了太久  多校博客直接从第三场跳到了第九场orz 见谅见谅(会补的!) 明明最后看下来是dp场 但是硬生生被我们做成了组合数专场…… 听说jls把我们用组合数做的题都用dp来了遍 这里只放了用组 ...

  6. 杭电多校第九场 hdu6425 Rikka with Badminton 组合数学 思维

    Rikka with Badminton Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/O ...

  7. Rikka with Game[技巧]----2019 杭电多校第九场:1005

      Rikka with Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Othe ...

  8. 杭电多校第九场 hdu6424 Rikka with Time Complexity 数学

    Rikka with Time Complexity Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K ( ...

  9. 杭电多校第九场 HDU6415 Rikka with Nash Equilibrium dp

    Rikka with Nash Equilibrium Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K ...

随机推荐

  1. Jennifer Chayes: 生活始终在你手中

    Jennifer Chayes ​​听到Mark Kac.Freeman J. Dyson.林家翘,或者是David I. Gottlie.BerndSturmfels和Sir John Ball等 ...

  2. linux-深度学习环境配置-Centos

    下载Centos 7安装镜像,制作启动优盘. Install CentOS 7 安装CentOS 7. 第一步,配置日期.语言和键盘. 第二步,选择-系统-安装位置,进入磁盘分区界面.选择-其它存储选 ...

  3. WTF is The BlockChain?

    最近区块链大热,走到哪儿都有人在讨论区块链和比特币,甚至于一些对密码学完全没有概念的人都开始大肆吹捧,不免让人嗤之以鼻.相信很多技术和非技术的朋友都希望能够更深层次地去了解它是如何工作的.本文将用不到 ...

  4. 人心和隐私怎么防?“防出轨”APP让道德滑落

    ​ 王尔德曾说过,"一个人应该永远保持一点神秘感".让·保·里克特也表示,:"一个人泄露了秘密,哪怕一丝一毫,就再也得不到安宁了".可见,对于自然人来说,保有自 ...

  5. 2020年JAVA大厂笔经面经

    个人简介 ​ Java后台开发方向. 非计算机专业硕士,专业涉及到一些开发. 实验室项目主要是Java Web系统,挖掘小亮点. 无实习经验. 闲话唠嗑 ​ 回顾这几个月,宛若梦一场. 一开始心态不好 ...

  6. 探究 Go 语言 defer 语句的三种机制

    Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer ...

  7. 分割文件和数据(linux)

    在某些情况下,必须把文件分割成多个更小的片段.如今我们分割文件的目的比如:提高可读性.生成日志.通过Email发送文件等等. 假设我们有一个erro.log的测试文件,其大小为14M.你可以将该文件分 ...

  8. 名企6年Java程序员的工作感悟,送给迷茫的你

    程序员从开始选择到坚持下去,工作了六年对一个程序员意味什么?在职位上:高级开发工程师?架构师?技术经理?or ... ?在能力上:各种编码无压力?核心代码无压力?平台架构无压力? or ... fuc ...

  9. 跟我猜Spring-Boot:bean的创建

    废话在前 最近几年的技术路子很杂,先是node,然后是php,后来是openresty,再后来转到了java,而接触的框架(Framework),也越发的复杂,从最开始的express/koa,到lu ...

  10. 【jQuery学习日记】jQuery实现滚动动画

    需要实现的效果 样式分析: 2个主要部分,头部的标题和导航部分,和主要的功能实现区域: 1.头部 <div id="header"> <h1>动漫视频< ...