(AtCoder Beginner Contest 321)(退背包,二叉树)

A.直接暴力即可

​
#include
using namespace std;
const int N =2e5+10;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;

void solve(){
    string s;
    cin>>s;
    for(int i=1;i>t;
    while(t--) solve();
}

​

B.也是暴力枚举每个分数即可

#include
using namespace std;
const int N =2e5+10;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;
int a[N];
void solve(){
    cin>>n>>m;
    for(int i=1;i>a[i];
    }
    int res=INT_MAX;
    for(int j=0;j<=100;j++){
        vector b;
        for(int i=1;i=m){
            res=min(res,j);
        }
    }
    if(res==INT_MAX){
        cout<<-1;
        return ;
    }
    cout<>t;
    while(t--) solve();
}

C.我二分+数位dp了

直接二分当前数的范围内有多少个 “321”的数的个数

import random
import sys
import os
import math
from collections import Counter, defaultdict, deque
from functools import lru_cache, reduce,cache
from itertools import accumulate, combinations, permutations
from heapq import nsmallest, nlargest, heapify, heappop, heappush
from io import BytesIO, IOBase
from copy import deepcopy
import threading
import bisect

BUFSIZE = 4096


class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = "x" in file.mode or "r" not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b"\n") + (not b)
            ptr = self.buffer.tell()
            self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            self.buffer.truncate(0), self.buffer.seek(0)


class IOWrapper(IOBase):
    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode("ascii"))
        self.read = lambda: self.buffer.read().decode("ascii")
        self.readline = lambda: self.buffer.readline().decode("ascii")


sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip("\r\n")


def I():
    return input()


def II():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return list(input().split())


def LII():
    return list(map(int, input().split()))


def GMI():
    return map(lambda x: int(x) - 1, input().split())


def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))


def solve():
    k = II()


    @cache
    def dfs(i: int, limit: bool, num: bool, pre: int,s:str) -> int:
        if i == len(s):
            return int(num)
        res = 0
        if not num: res = dfs(i + 1, False, False, 10,s)
        up = int(s[i]) if limit else 9
        di = 0
        if not num: di = 1
        for d in range(di, up + 1):
            if pre > d:
                res += dfs(i + 1, limit and d == up, True, d,s)
        return res

    l, r = 1, 10 ** 18

    while l < r:
        mid = (l + r) >> 1
        if dfs(0, True, False, 10,str(mid)) >= k:
            r = mid
        else:
            l = mid + 1
    print(l)


if __name__ == '__main__':
    for _ in range(1):
        solve()

D.

每个ai都要乘每个bi

排序后双指针维护当前ai+bi<=k的最有边界即可

#include
using namespace std;
const int N =2e5+10;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m,k;
int a[N],b[N];
void solve(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];    
    }
    for(int j=1;j<=m;j++) cin>>b[j];
    sort(a+1,a+1+n);
    sort(b+1,b+1+m);
    int res=0;
    int now=0;
    for(int j=1;j<=m;j++) now+=b[j];
    int idx=m;
   
    for(int i=1;i<=n;i++)
    {
        while(idx>=1&&a[i]+b[idx]>=k)
        {
            now-=b[idx];
            idx--;
        }
    //    cout<>t;
    while(t--) solve();
}

E.

直接get函数就是找以当前x为根节点的子树下面距离为k的有多少个数,最大值是n

那么最左边界是x<

然后往父节点跳即可,边跳边计算父节点的另一个儿子节点

#include
using namespace std;
const int N =2e5+10,mod= 998244353;
#define int long long
typedef long long LL;
typedef pair PII;



void solve()
{

    int n,x,k;
    
    int res=0;
    auto get=[&](int x,int k,int n){
        if(k>=64) return 0ll;
        if(k<0) return 0ll;
        __int128 num=1ll<n) return 0ll;
        LL res=min(r,(__int128)n)-l+1;
        return res;
    };
    
    cin>>n>>x>>k;
    if(k)
    {
        res+=get(x,k,n);
    }
    while(x>1&&k>0){
        k--;
        res+=get((x^1),k-1,n);
        x/=2;
    }
    if(k==0&&x){
        res++;
    }
    cout<>t;
    while(t--) solve();
}

F:退背包问题

添加就是正常的01背包

然后删除就是

维护g数组

状态是,不选当前球,体积为i的方案数

那么g[i]=f[i]-g[i-x]

考虑容斥原理

不选当前球体积为i=选+不选当前球体积为i-选当前球体积为i的方案数

=f[i]-g[i-x]

g[i-x]可以理解为选了这个球后,剩下的 i−x�−�就是由不选该球的方案数组成

#include
using namespace std;
const int N =2e5+10,mod= 998244353;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;
int a[N];
int dep[N];


void solve()
{
    int q,k;
    cin>>q>>k;
    vector f(k+1,0);
    f[0]=1;
    while(q--){
        string op;
        int x;cin>>op>>x;
        if(op[0]=='+'){
            for(int i=k;i>=x;i--){
                f[i]+=f[i-x];
                f[i]%=mod;
            }
        }
        else
        {
            //不选该球和为j的方案书
            //选和不选
            vector g(k+1,0);
            for(int i=0;i<=k;i++){
                if(i>t;
    while(t--) solve();
}

你可能感兴趣的:(算法)