BZOJ3233【AHOI2013】找硬币
生活随笔
收集整理的這篇文章主要介紹了
BZOJ3233【AHOI2013】找硬币
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題面
題解
最優肯定是盡可能用大面值硬幣
設$f[i]$表示最小面值為$i$時的最小答案
則:(令$p$是$i$的最小質因子)
$$ f[\frac ip]=min(f[\frac ip], f[i] + \sum_{j=1}^n(a[j] \% i) / (i / p)) $$
用線性篩預處理每個數的最小質因子$low[i]$,按照上式轉移即可。
代碼
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define RG register #define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout); #define clear(x, y) memset(x, y, sizeof(x))inline int read() {int data = 0, w = 1; char ch = getchar();while(ch != '-' && (!isdigit(ch))) ch = getchar();if(ch == '-') w = -1, ch = getchar();while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();return data * w; }const int maxn(400010); int a[maxn], f[maxn], low[maxn], prime[maxn], n, cnt, max; bool not_prime[maxn];void Init() {low[1] = 1, not_prime[1] = 1;for(RG int i = 2; i <= max; i++){if(!not_prime[i]) prime[++cnt] = low[i] = i;for(RG int j = 1; j <= cnt && i * prime[j] <= max; j++){not_prime[i * prime[j]] = true;low[i * prime[j]] = prime[j];if(i % prime[j] == 0) break;}} }int main() {n = read();for(RG int i = 1; i <= n; i++)max = std::max(max, a[i] = read());Init(); clear(f, 63);for(RG int i = max; i; i--){int sum = 0;for(RG int j = 1; j <= n; j++) sum += a[j] / i;f[i] = std::min(f[i], sum);for(RG int x = i; x > 1;){int y = i / low[x], sum = 0;for(RG int j = 1; j <= n; j++) sum += (a[j] % i) / y;f[y] = std::min(f[y], f[i] + sum), y = low[x];while(x % y == 0) x /= y;}}printf("%d\n", f[1]);return 0; }轉載于:https://www.cnblogs.com/cj-xxz/p/10220575.html
總結
以上是生活随笔為你收集整理的BZOJ3233【AHOI2013】找硬币的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 214. 最短回文串
- 下一篇: 【原】Coursera—Andrew N