Yogurt factory, 2005 Mar
加上维护费用,计算出实际成本然后贪心。
本题要注意long long
const int maxn = 10010;
ll c[maxn], a[maxn], d, n;
int main()
{
scanf("%lld%lld", &n, &d);
rep(i, n) scanf("%lld%lld", &c[i], &a[i]);
ll now = 10010, ans = 0;
rep(i, n){
now = min(now + d, c[i]);
ans += now * a[i];
}
printf("%lld\n", ans);
return 0;
}
Buying Feed II, 2010 Jan
计算出加上油价后的实际价格,按照从小到大的顺序进行购买。
const int maxn = 10010;
struct node{
int x, f, c, p;
node(int _x = 0, int _f = 0, int _c = 0) : x(_x), f(_f), c(_c) {}
};
node a[maxn];
int cmp(node x, node y){
return x.p < y.p;
}
int k, e, n;
int main()
{
scanf("%d%d%d", &k, &e, &n);
rep(i, n) {
scanf("%d%d%d", &a[i].x, &a[i].f, &a[i].c);
a[i].p = a[i].c + e - a[i].x;
}
sort(a, a + n, cmp);
int ans = 0;
rep(i, n){
int cnt = min(k, a[i].f);
k -= cnt;
ans += a[i].p * cnt;
if (k == 0) break;
}
printf("%d\n", ans);
return 0;
}
Profits, 2011 Jan
经典的最大连续和问题,dp或者计算前缀和皆可
const int maxn = 100010;
int a[maxn], d[maxn];
int main()
{
int n; scanf("%d", &n);
rep1(i, n) scanf("%d", &a[i]);
rep1(i, n) d[i] = d[i-1] > 0 ? d[i-1] + a[i] : a[i];
int ans = -10000;
rep1(i, n) ans = max(ans, d[i]);
printf("%d\n", ans);
return 0;
}
Allowance, 2005 Oct
本题我只想到了每个月进行一次处理的办法,暂时没有批量计算的办法。
先把单张数额超过额定工资的部分发完。
然后进行”常规”工资发放。思路:在不浪费的情况下,尽量多花面额较大的币种。这样一遍花完可能就把工资发完了,如果没有发完,找面额最小的币种发一份即可。
但这么做的正确性存疑,我没有比较好的证明
const int maxn = 50;
struct money{
ll v, k;
money(ll _v = 0, ll _k = 0) : v(_v), k(_k){}
};
money a[maxn];
int n;
ll c;
int cmp(money x, money y){
return x.v > y.v;
}
bool test(){
ll now = c;
rep(i, n) if (a[i].k){
ll tmp = min(a[i].k, now / a[i].v);
now -= tmp * a[i].v;
a[i].k -= tmp;
}
if (now == 0) return true;
for(int i = n-1; i >= 0; i--) if (a[i].k){
a[i].k--;
return true;
}
return false;
}
int main()
{
scanf("%d%lld", &n, &c);
rep(i, n) scanf("%lld%lld", &a[i].v, &a[i].k);
sort(a, a + n, cmp);
ll ans = 0;
rep(i, n) if (a[i].v >= c){
ans += a[i].k;
a[i].k = 0;
}
while(test()) {
++ans;
//rep(i, n) printf("%lld %lld\n", a[i].v, a[i].k);pn;
}
printf("%lld\n", ans);
return 0;
}
Monthly Expense, 2007 Mar
一个普通的二分答案题,二分之后尽量还款
const int maxn = 100010;
ll n, m, a[maxn];
bool test(ll x){
ll sum = 0, tot = 0;
rep(i, n){
if (a[i] > x) return 0;
if (tot + a[i] <= x) tot += a[i];
else {
tot = a[i];
sum++;
}
}
sum++;
return sum <= m;
}
int main()
{
scanf("%lld%lld", &n, &m);
rep(i, n) scanf("%lld", a + i);
ll l = 0, r = 60000LL * 10000, mid, ans = r;
while(r >= l){
mid = (l+r) / 2;
if (test(mid)){
ans = mid;
r = mid - 1;
}else l = mid + 1;
}
printf("%lld\n", ans);
return 0;
}
Cow Laundry, 2003 Fall
建立相关映射之后直接求逆序数对,数据小暴力求逆序数对即可
const int maxn = 1010;
int a[maxn], b[maxn], ra[maxn], c[maxn], n;
int main()
{
scanf("%d", &n);
rep(i, n) scanf("%d%d", &a[i], &b[i]);
rep(i, n) ra[a[i]] = i;
rep(i, n) c[i] = ra[b[i]];
int ans = 0;
rep(i, n) For(j, i+1, n-1) if (c[i] > c[j]) ++ans;
printf("%d\n", ans);
return 0;
}