Finals [Online Mirror, Div. 2] F題
Splitting money
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
After finding and moving to the new planet that supports human life, discussions started on which currency should be used. After long negotiations, Bitcoin was ultimately chosen as the universal currency.
These were the great news for Alice, whose grandfather got into Bitcoin mining in 2013, and accumulated a lot of them throughout the years. Unfortunately, when paying something in bitcoin everyone can see how many bitcoins you have in your public address wallet.
This worried Alice, so she decided to split her bitcoins among multiple different addresses, so that every address has at most xx satoshi (1 bitcoin = 108108 satoshi). She can create new public address wallets for free and is willing to pay ff fee in satoshi per transaction to ensure acceptable speed of transfer. The fee is deducted from the address the transaction was sent from. Tell Alice how much total fee in satoshi she will need to pay to achieve her goal.
Input
First line contains number NN (1≤N≤2000001≤N≤200000) representing total number of public addresses Alice has.
Next line contains NN integer numbers aiai (1≤ai≤1091≤ai≤109) separated by a single space, representing how many satoshi Alice has in her public addresses.
Last line contains two numbers xx, ff (1≤f<x≤1091≤f<x≤109) representing maximum number of satoshies Alice can have in one address, as well as fee in satoshies she is willing to pay per transaction.
Output
Output one integer number representing total fee in satoshi Alice will need to pay to achieve her goal.
Example
Input
Copy
3 13 7 6 6 2
Output
Copy
4
Note
Alice can make two transactions in a following way:
0. 13 7 6 (initial state)
1. 6 7 6 5 (create new address and transfer from first public address 5 satoshies)
2. 6 4 6 5 1 (create new address and transfer from second address 1 satoshi)
Since cost per transaction is 2 satoshies, total fee is 4.
思路:
先說一下題意,大致就是給你一些整數序列a,並給出一個限制x,和花費f,對於序列中的每個數ai,要把ai分成不大於x的一些數,每分一次需要花費f,求最小花費
很明顯,每次等分是最小的花費策略,但是要保證分到最後是x才花費最少,於是貪心,對一一個數ai,我們先分出最大的
2^p * x(即分成了p份),需要花費(2^p - 1 + 1)* f(1 + 2 + 4 + ........ + 2……2^(p - 1) = 2^p - 1,最後又+1是因為第一次分成2^p * x和ai - 2^p * x也需要一次花費) = 2^p * f,剩下的仍然這樣分,這樣就剩下一個問題,如果最後剩下的恰好要分卻只能分得1,如樣例中的7,這樣肯定是不符合上述規律的,這樣我們只需要特判一下 x + 1 <= ai <= x + f的情況即可
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn = (ll)2e5 +10;
ll a[maxn],p[35],pos = 0;
void init()
{
ll w = 1;
for (int i = 0;i < 31;i ++)
{
p[pos ++] = w;
w *= 2;
}
pos --;
}
int main()
{
init();
ll n,f,x;
scanf("%lld",&n);
for (int i = 0;i < n;i ++)
scanf("%lld",&a[i]);
scanf("%lld %lld",&x,&f);
ll ans = 0;
for (int i = 0;i < n;i ++)
{
if (a[i] > x)
for (int j = pos;j >= 0;j --)
{
ll t = p[j] * (x + f);
if (t + 1 <= a[i])
{
ans += p[j] * f;
a[i] -= t;
}
}
if (a[i] > x && a[i] <= x + f)
ans += f;
}
printf("%lld\n",ans);
return 0;
}