【AtCoder】ARC096 CF Problem Solution

I heard that Japanese question thinking is very good, go to increase your IQ qwq

C - Half and Half

answer

It’s okay to enumerate how many AB pizzas you buy,
but the final total cost of buying x AB pizzas is a unimodal function, and you can get three points.
This question is a bit like the six-province joint entrance exam 2017D1T1 final exam

code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 100005
#define PLI pair<long long,int>
#define fi first
#define se second
#define mp make_pair
//#define ivorysi
using namespace std;
typedef long long int64;
int64 A,B,C;
int X,Y;
int64 calc(int t) {
    return 2 * t * C + max(X - t,0) * A + max(Y - t,0) * B;
}
void Solve() {
    scanf("%lld%lld%lld%d%d",&A,&B,&C,&X,&Y);
    int L = 0,R = max(X,Y);
    while(1) {
        int k = (R - L) / 3;
        if(!k) break;
        if(calc(L + k) > calc(R - k)) L = L + k;
        else R = R - k;
    }
    int64 ans = X * A + Y * B;
    for(int i = L ; i <= R ; ++i) {
        ans = min(ans,calc(i));
    }
    printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

D - Static Sushi

answer

It's good to have a discussion about the classification, go clockwise, go counterclockwise, go clockwise and go counterclockwise, go counterclockwise and go clockwise

code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 100005
#define PLI pair<long long,int>
#define fi first
#define se second
#define mp make_pair
//#define ivorysi
using namespace std;
typedef long long int64;
int N;
int64 C,x[MAXN],v[MAXN],ans;
int64 pre[MAXN],suf[MAXN],premax[MAXN],sufmax[MAXN];
void Solve() {
    scanf("%d%lld",&N,&C);
    for(int i = 1 ; i <= N ; ++i) scanf("%lld%lld",&x[i],&v[i]);
    x[N + 1] = C;
    for(int i = 1 ; i <= N ; ++i) {
        pre[i] = pre[i - 1] + v[i] - (x[i] - x[i - 1]);
        premax[i] = max(pre[i],premax[i - 1]);
    }
    for(int i = N ; i >= 1 ; --i) {
        suf[i] = suf[i + 1] + v[i] - (x[i + 1] - x[i]);
        sufmax[i] = max(suf[i],sufmax[i + 1]);
    }
    ans = max(ans,max(sufmax[1],premax[N]));
    for(int i = 1 ; i <= N ; ++i) {
        ans = max(ans,pre[i] - x[i] + sufmax[i + 1]);
    }
    for(int i = N ; i >= 1 ; --i) {
        ans = max(ans,suf[i] - (C - x[i]) + premax[i - 1]);
    }
    printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

E - Everything on It

answer

Tolerance and exclusion, w(i) means that there are i ingredients that appear less than 2 times. The
formula is \(\sum_{i = 0}^{n}(-1)^{i}\binom{n}{i}w( i)\)
Then consider finding \(w(i)\)
and then consider a \(w2(i,j)\) means to divide i numbers into j bowls, there can be numbers that are not divided into bowls, use Similar to the recursion method of the second type of Stirling number,
then the number of solutions is \(w(i) = \sum_{j = 0}^{i} w2(i,j)2^{(N - i )j}2^{2^{N - i}}\)
Then you can solve \(O(n^2)\)

code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 100005
#define PLI pair<long long,int>
#define fi first
#define se second
#define mp make_pair
//#define ivorysi
using namespace std;
typedef long long int64;
int N,M;
int64 C[3005][3005],S[3005][3005],ans;
 
int64 fpow(int64 x,int64 c,int64 MOD) {
    int64 res = 1,t = x;
    while(c) {
        if(c & 1) res = res * t % MOD;
        t = t * t % MOD;
        c >>= 1;
    }
    return res;
}
int64 ways(int x) {
    int64 res = 0;
    int64 tmp2 = fpow(2,fpow(2,N - x,M - 1),M);
    int64 t = fpow(2,N - x,M);
    int64 tmp1 = 1;
    for(int j = 0 ; j <= x ; ++j) {
        res += S[x][j] * tmp1 % M * tmp2 % M;
        tmp1 = tmp1 * t % M;
        res %= M;
    }
    return res;
}
void Solve() {
    scanf("%d%d",&N,&M);
    C[0][0] = 1;
    for(int i = 1 ; i <= N ; ++i) {
        C[i][0] = 1;
        for(int j = 1 ; j <= i ; ++j) {
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % M;
        }
    }
    S[0][0] = 1;S[1][1] = 1;
    for(int i = 1 ; i <= N ; ++i) {
        S[i][0] = 1;
        for(int j = 1 ; j <= i ; ++j) {
            S[i][j] = (S[i - 1][j - 1] + S[i - 1][j] * (j + 1)% M) % M;
        }
    }
    int t = 1;
    for(int i = 0 ; i <= N ; ++i) {
        (ans += t * C[N][i] % M * ways(i) % M) %= M;
        t = 1LL * t * (M - 1) % M;
    }
    printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

F - Sweet Alchemy

answer

The model transformation is very interesting. In the end, there are n kinds of items, (the cost of a point is the m sum of the subtree, and the value is the size of the subtree), each of which can choose D, and the No. 1 node can choose infinite
but... …I can rotate the model at most, and the rest is a very strange backpack. The
number of items is 50, the number of items, and the volume and volume are all \(10^9\).
Later, the explanation of the problem is that the value range is very small (the value is only 50), consider making articles on the value domain.
We set the value to \(Y\) and the cost to \(X\) , and arrange them from large to small according to \(Y_{i} / X_{i}\) The order of
greed is definitely wrong, but we consider such a situation, if there is a pair of \(p,q\) and \(p <= q\) , then if q is selected 50, p has 50 not yet If we choose, we can obviously choose \(Y_{q}\) p items, and choose \(Y_{p}\)
q items, so that the value we get has not changed, but the volume spent will be less. In this case, at most 50 items of each kind, it is good to make a backpack with a capacity of 50*50*50, which means the minimum volume required to achieve such a value, and then the remaining volume is used to greedily put the largest unit value.
Why is it right? If there are only two kinds of items, 50 items are selected, 10 more items for A, and 20 more items for B. If all 20 items of B are selected at this time, it is the best, but according to the above Replacement method, if the number of A is less than the value of B, then we will combine a few of the 50 selected to replace the originally selected B item, which ensures that if the greedy selection is made, if the remaining part of the A item can be selected as Almighty selected

code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define MAXN 1000005
#define PLI pair<long long,int>
#define fi first
#define se second
#define mp make_pair
#define ha 99994711
#define ba 823
//#define ivorysi
using namespace std;
typedef long long int64;
int N,Lim,dis;
int64 X,D,m[55],cost[55];
int p[55],siz[55],q[125005],id[55];
int64 dp[125005],ans;
int ql,qr;
bool cmp(int a,int b) {
    return siz[a] * cost[b] > siz[b] * cost[a];
}
void update(int64 &x,int64 y) {
    x = min(x,y);
}
void Solve() {
    scanf("%d%lld%lld",&N,&X,&D);
    Lim = N * N * N;
    scanf("%d",&m[1]);
    for(int i = 2 ; i <= N ; ++i) scanf("%d%d",&m[i],&p[i]);
    for(int i = N ; i >= 1 ; --i) {
        cost[i] += m[i];siz[i]++;
        cost[p[i]] += cost[i];siz[p[i]] += siz[i];
        id[i] = i;
    }
    for(int i = 1 ; i <= Lim ; ++i) dp[i] = X + 1;
    sort(id + 1,id + N + 1,cmp);
    dis = min(N,(int)D);
    for(int k = 1 ; k <= N ; ++k) {
        int s =  siz[id[k]];int64 v = cost[id[k]];
        for(int j = 0 ; j < s ; ++j) {
            int T = min((Lim - j)/ s,dis);
            if(id[k] == 1) T = min((Lim - j) / s,N);
            int p = (Lim - j) / s;
            ql = 1,qr = 0;
            for(int i = (Lim - j) / s ; i >= 1 ; --i) {
                while(p >= 0 && i - p <= T) {
                    while(ql <= qr && dp[j + q[qr] * s] - q[qr] * v > dp[j + p * s] - p * v) --qr;      
                    q[++qr] = p;
                    --p;
                }
                while(ql <= qr && q[ql] >= i) ++ql;
                if(ql <= qr) {
                    update(dp[j + i * s],dp[j + q[ql] * s] + (i - q[ql]) * v);
                }
            }
        }
    }
    for(int i = 0 ; i <= Lim ; ++i) {
        int64 T = X - dp[i];
        if(T < 0) continue;
        int64 tmp = i;
        int num;
        for(int k = 1 ; k <= N ; ++k) {
            if(id[k] == 1) num = T;
            else num = D - dis;
            int t = min(T / cost[id[k]],(int64)num);
            tmp += 1LL * t * siz[id[k]];
            T -= t * cost[id[k]];
        }
        ans = max(ans,tmp);
    }
    printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325184624&siteId=291194637