题目链接

题目大意

使用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. 全栈新视觉——前后端分离

    1234 前端工程化从单纯的 HTML/CSS/JavaScript,到 gulp/webpack 以及 node.js.可能还需要其他的插件 sass.less.vue.react.angular. ...

  2. 改进"尽最大努力交付"的服务

    改进"尽最大努力交付"的服务 网络层的作用就是负责在不同的网段尽力转发数据包,但是负责中专数据包的路由器并不关心数据包的内容和优先顺序.而是先到达的数据包先处理,后到达的数据包排队 ...

  3. 硬件小白学习之路(1)稳压芯片LM431

    图稳压芯片LM431简介 偶然的机会接触到LM431这个芯片,周末晚上打发无聊的时光,查资料进行剖析. LM431的Symbol Diagram和Functional Diagram如图1所示,下面分 ...

  4. 树莓派3B安装OpenWrt打造超级路由器

    网上有很多树莓派安装OpenWrt的教程,我这里写一下个人安装体验以及踩过的坑

  5. vmware workstaion之不能连接外网

    Vmwareworkstation15系列桥接模式不能上网解决办法 最近在vmwareworkstation15中创建一个双网卡虚拟机,由于一直连不了外网,一直困扰着我.各种姿势在百度谷歌查找,最终还 ...

  6. 从头认识js-js的发展历史

    JavaScript简介 JavaScript诞生于1995年,当时,它的主要目的是处理以前有服务端语言(如Perl)负责的一些输入验证操作. JavaScript简史 1995年2月当时就职于Net ...

  7. 统计 Django 项目的测试覆盖率

    作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 我们完成了对 blog 应用和 comment 应用这两个核心 app 的测试.现在 ...

  8. echart 之实现温度计

    百度这个图表支持不是很好,有的需要自己写,看大神们实现温度计都是用 水球特效实现的我这里雕虫小计啊但是满足我了我的项目需求特此分享出来,可惜自己不是专业的前端 这是我的实现结果 好了上代码html: ...

  9. hadoop之完全分布式集群配置(centos7)

    一.基础环境 现在我们有两台虚拟机了,再克隆两台: 克隆好之后需要做三件事:1.更改主机名称 2.修改ip地址 3.将ip地址和对应的主机号加入到/etc/hosts文件中 1.永久修改主机名 hos ...

  10. W3C的盒子模型和IE的盒子模型

    盒子模型分为两种:W3C盒子模型(标准盒子模型)和IE盒子模型 盒子模型组成:content+padding+border+margin 标准盒子模型的width就是content 而IE盒子模型的w ...