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补题)的主要内容,如果未能解决你的问题,请参考以下文章