AtCoder Beginner Contest 231(EF补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 231(EF补题)相关的知识,希望对你有一定的参考价值。

E - Minimal payments

题意:

N N N种面值的钱币,现在需要支付 X X X元,现在定义 A A A为支付的钞票数, B B B为找钱找回来的钞票数,问 A + B A+B A+B最小是多少?

思路:

直接记忆化搜索,金额较大,所以开 m a p map map
定义 f ( n , x ) f(n,x) f(n,x)为前 n n n种钞票支付 x x x元的情况下,最小的 A + B A+B A+B
那么此时为了让 A + B A+B A+B最小,一定是尽可能用大钞票,所以
f ( n , x ) = f ( n − 1 , x % a [ n ] ) + x / a [ n ] f(n,x)=f(n-1,x \\%a[n])+x/a[n] f(n,x)=f(n1,x%a[n])+x/a[n],代表尽可能的用 a [ n ] a[n] a[n]这种钞票,使得用前 n − 1 n-1 n1种钱,解决剩下的钱。
如果 x % a [ n ] = 0 x\\%a[n]=0 x%a[n]=0,那么说明不需要找钱,所以就不需要第二种策略了
反之可能需要第二种策略
f ( n , x ) = f ( n − 1 , a [ n ] − ( x % a [ n ] ) ) + x / a [ n ] + 1 f(n,x)=f(n-1,a[n]-(x\\%a[n]))+x/a[n]+1 f(n,x)=f(n1,a[n](x%a[n]))+x/a[n]+1,这个的含义就是多给一张 a [ n ] a[n] a[n]这种金额的钱,前 n − 1 n-1 n1种钱来解决剩下的钱。
所以就是上述两种策略的最小值

#include<bits/stdc++.h>
using namespace std;
const int N=70;
using ll = long long ;
ll n,x;
ll a[N];
map<int,ll> f[N];

ll dfs(int n,ll x) 
    if(n==1) 
        return x;
    
    if(x==0) 
        return 0;
    

    if(f[n].find(x)!=f[n].end()) 
        return f[n][x];
    

    f[n][x]=dfs(n-1,x%a[n])+x/a[n];

    if(x%a[n]) 
        f[n][x]=min(f[n][x],dfs(n-1,a[n]-(x%a[n]))+x/a[n]+1);
    
    return f[n][x];

int main() 
    cin>>n>>x;
    for(int i=1;i<=n;i++) 
        cin>>a[i];
    

    cout<<dfs(n,x)<<endl;



F - Jealous Two

题意:

现在给定 N N N个物品,有 2 2 2个人,对每种物品的评价分别为 A i A_i Ai B i B_i Bi,让你求 ∑ i = 1 n ∑ j = 1 n [ A i ≥ A j & & ≤ B i ≤ B j ] \\sum \\limits_i=1 ^n\\sum \\limits_j=1 ^n[A_i≥A_j\\&\\&≤B_i≤B_j] i=1nj=1n[AiAj&&BiBj]

思路:

可以用所有情况,即 N 2 N^2 N2减去不符合的情况数量
不符合的情况就是 A i < A j ∣ ∣ B i > B j A_i<A_j||B_i>B_j Ai<AjBi>Bj
那么就直接找 A i < A j A_i<A_j Ai<Aj的数量和 B i > B j B_i>B_j Bi>Bj的数量,再次减去 A i < A j & & B i > B j A_i<A_j\\&\\&B_i>B_j Ai<Aj&&Bi>Bj的数量(因为算重了,容斥)
前面两种数量直接排完序后,直接计数即可
最后一种情况利用树状数组来求即可,就类似于求逆序对的数量。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
#define ll long long
struct node 
    int x;
    int id;
    bool operator<(const node &t) const  return x < t.x; 
 a[N], b[N];
int n;
int A[N], B[N];
int tr[N];
int lowbit(int x)  return x & (-x); 
void Insert(int x) 
    for (int i = x; i <= n; i += lowbit(i)) 
        tr[i]++;
    


int Query(int x) 
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) 
        res += tr[i];
    
    return res;


int main() 
    cin >> n;
    for (int i = 1; i <= n; i++) 
        cin >> a[i].x;
        a[i].id = i;
    
    sort(a + 1, a + n + 1);

    int cnt = 0;
    for (int i = 1; i <= n; i++) 
        if (i == 1 || a[i].x != a[i - 1].x) 
            cnt++;
        
        A[a[i].id] = cnt;
    

    for (int i = 1; i <= n; i++) 
        cin >> b[i].x;
        b[i].id = i;
    
    sort(b + 1, b + n + 1);
    cnt = 0;
    for (int i = 1; i <= n; i++) 
        if (i == 1 || b[i].x != b[i - 1].x) 
            cnt++;
        
        B[b[i].id] = cnt;
    
    ll res = 0;
    int r = n;
    while (r) 
        int l = r;
        for (; l && a[l].x == a[r].x; l--) 
            res += n - r;
        
        r = l;
    

    r = n;
    while (r) 
        int l = r;
        for (; l&&b[l].x == b[r].x; l--) 
            res += n - r;
        
        r = l;
    

    r = n;
    while (r) 
        int l = r;
        for (; l&&a[l].x == a[r].x; l--) 
            res -= Query(B[a[l].id] - 1);
        
        l = r;

        for (; l&&a[r].x == a[l].x; l--) 
            Insert(B[a[l].id]);
        
        r = l;
    
    printf("%lld\\n", 1ll * n * n - res);


To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于AtCoder Beginner Contest 231(EF补题)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242