zoukankan      html  css  js  c++  java
  • [BZOJ]4265 货币系统

    题意

    一个货币系统要求一共有 m 种货币,并且将它们按照币值从小到大排好序以后,前一个货币币值乘上 x 等于后一个货币币值,(x ∈ {2, 3, 4, 5}),且最小的币值一定为 1。

    请设计一个货币系统,使得它表示总币值为 n 的钱所需的货币总张数最少。

    (n ≤ 10^18)
    (m ≤ 100)
    Source : BZOJ 4265

    题解

    下一个货币照顾不到前一个货币能照顾的情况。

    假如说x只有一个,就是x进制,其实x有四个跟一个没有区别的。

    最终可以把n写成这样的一个式子

    [n=1*(k_1*(a_1+(k_2*(a_2+...)))) ]

    最终的答案数应该是(a_1+a_2+dots+a_n)

    只要按照进制的算法,每次除(k_i)取余求一个最小值就行了。

    注意这里n比较大,但是实际上用到的状态数其实很小,可以用map代替数组。

    时间复杂度(O(mlog^3n))

    #include <bits/stdc++.h>
    #define int long long
    #define Mid ((l + r) >> 1)
    #define lson (rt << 1)
    #define rson (rt << 1 | 1)
    using namespace std;
    int read(){
    	char c; int num, f = 1;
    	while(c = getchar(),!isdigit(c)) if(c == '-') f = -1; num = c - '0';
    	while(c = getchar(), isdigit(c)) num = num * 10 + c - '0';
    	return f * num;
    }
    int n, m;
    map<int,int> f[105];
    int dfs(int x, int y) {
    	if(f[x].count(y)) return f[x][y];
    	if(y == 0) return 0;
    	if(x == 1) return y;
    	int minn = 1e18;
    	for(int i = 2; i <= 5; i++) 
    		minn = min(minn, dfs(x - 1, y / i) + y % i);
    	f[x][y] = minn;
    	return f[x][y];
    }
    signed main()
    {
    	n = read(); m = read();
    	printf("%lld
    ", dfs(m, n));
    	return 0;
    }
    
  • 相关阅读:
    还能这样偷懒?用Python实现网站自动签到脚本
    普通爬虫 VS 多线程爬虫!Python爬虫运行时间对比
    中文文献阅读方法及笔记模板
    约束
    可迭代对象补充
    练习题及补充
    内置函数的补充/super/异常值处理
    特殊成员
    嵌套
    面向对象知识点总结补充
  • 原文地址:https://www.cnblogs.com/onglublog/p/14385535.html
Copyright © 2011-2022 走看看