TOJ 4453
来源:互联网 发布:win10仿mac桌面dock 编辑:程序博客网 时间:2024/06/07 00:25
题目标题:
Cards
题目连接:
http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4453
题目类型:
模拟
数据结构:
无
思路分析:
类似于背包问题那样
一共5种卡片, 各有无限张
需要找出N张卡( 假设其中 1 有a1张, 2 有a2 张.... )
让其平均数 ( a1 *1 + a2 * 2 + a3 * 3 ...) / ( a1 + a2 + a3 ....)
精确的等于给定的值P,
既然这个P是符合规则的实数,且可能令N非常的大
所以不能单纯用背包思路来解决
首先要做的 先要吧P转换成整数, 并且假设一个整数来表示一共的张数
只要凑齐 这N张张数 并且值等于P的整数形式的 即可
并且需要符合最少张数这个条件
假如P为4.135
则我们知道 由 a1*1 + a2 * 2 ...得到的值除以总张数N就是 4.135
所以可以表现成 ( a1*1 + a2 * 2 ... ) / ( a1 + a2 + a3 ....) = 4.135 -> ( a1*1 + a2 * 2 ... ) / N = 4.135
要让张数最小 则对这个分数进行约分即可
则变成 4135 / 1000
最后只要让 N = 1000, ( a1*1 + a2 * 2 ... ) = 4135 就可以
这里有个小技巧
就是让牌乘起来刚好要大过 4135 然后继续减掉它跟 4135的差 那必定就是答案
就比如
大过4135 的排是1000张5的牌 这样 这1000张的总值是5000 并不是4135
则我们需要保持张数 又要让值减到4135
我们只需减去5000 - 4135 就可以了
因为我们能凑出单位1的值 那就是 5-4
所以 要保持张数 又要让值减5000 - 4135
最简单的办法就是 减去 这么多张5 再加回这么多张4 就可以了
既然题目说任意一种情况即可
那这就是最简单的情况了
证明:
要从中选N张卡片 让他们的总值除以N等于P
则我们得到 总值/N = P
因为 卡的种类和张数都是整数 所以这里的总值和N也只能是整数
所以我们可以转化P = P / 1 = P * 10000000 / 10000000;
这样的话 我们就得到 一个分子分母都是整数的分式 且答案等于P
那么这样的情况N并不是最小值 则我们对其进行约分
假设最简单分数 K/N = P 那我们就知道不存在更加少的情况了
因为
K/N=P 我们另N减去一个变量Z 就得到 K / ( N - Z ) = P 分母变小 我们需要让 分子变小来保持 分式的结果等于P 则得到 ( K - Y ) / ( N - Z ) = P
如果等式成立 则 原来的等式 K/N=P 必定不是最简分式
所以此时 的N 必然是正确且最小的
源代码:
#include <stdio.h>#include <string.h>#include <iostream>using namespace std;typedef __int64 int64;int64 _gcd( int64 a, int64 b ){if( !b ){return a;}return _gcd( b, a % b );}int64 _cvrt( string c ){int64 i, zz= 0;string tmp = "";for( int i = 0; i < c.length(); i ++ ){if( c[i] != '.' ){tmp += c[i];}}tmp = tmp + string( 10, '0' );for( i = 0; i < 10; i ++ ){zz = zz * 10 + tmp[i] - '0';}return zz;}int main(){int64 i;double inp;string str = "";cin >> str;int64 arr[6] = { 0 };int64 fm = 1000000000, fz = _cvrt( str );int64 tmp = _gcd( fm, fz );fm /= tmp;fz /= tmp;for( i = 1; i <= 5; i ++ ){if( fm * i > fz ){arr[i] = fm;break;}else if( fm * i == fz ){arr[i] = fm;i = -1;break;}}if( i != -1 ){arr[i - 1] = i * fm - fz;arr[i] -= arr[i - 1];}for( i = 1; i <= 5; i ++ ){if( i != 1 ){printf( " " );}printf( "%I64d", arr[i] );}printf( "\n" );return 0;}
注意:
这里输入的实数不能用double
因为 会产生丢失精度的情况
假设 输入4.9 则会变成4.89999999 的情况
所以只能用字符串输入 然后转换成整形
- TOJ 4453
- TOJ 2976
- toj 3140
- toj 1153
- TOJ 1772
- TOJ 3250
- TOJ 3051
- TOJ 4303
- TOJ 1005
- TOJ 1545
- TOJ 2378
- TOJ 1537
- TOJ 1252
- TOJ 1408
- TOJ 1509
- TOJ 2882
- TOJ 1052
- TOJ-ACM
- 操作系统(7)进程间通信
- 最优化/Optimization文章合集
- PAT 1018
- css宽度自适应
- UVa 11995 I Can Guess the Data Structure! (STL)
- TOJ 4453
- Eclipse如何导入jar包(referenced libraries)
- Matlab判断3个数是否互质
- Android中的事件分发机制
- 通过ATL COM组件实现在RichEdit中各种图片的显示(包括Gif图片的显示)
- 网络字节序
- HDU 3537 Daizhenyang's Coin 翻硬币博弈
- socket
- vimperator部分使用帮助