日常刷题2025-3-21

日常刷题2025-3-21

D. Tree Jumps

rating:1600

https://codeforces.com/contest/2070/problem/D

思路:方案数DP

看到求方案数,就先给DP预定好位置。分析一下题意,发现一个节点的方案数会来自它父亲的兄弟节点的方案数,所以我们只要从上往下,当求下面层的方案数时上一层的方案数已经求出来了。所以就是DP

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int N = 1e5+5;



template<typename T>
T power(T a, i64 b) {
    T ret = 1;
    while (b) {
        if (b & 1) ret = ret * a;
        a = a * a;
        b >>= 1;
    }
    return ret;
}

template<int P>
struct ModInt {
    int val;

    static inline int norm(int x) {
        if (x < 0)  x += P;
        if (x >= P) x -= P;
        return x; 
    }

    ModInt operator - () const { return ModInt(P - val); }
    inline ModInt inv() const { return power(*this, P - 2); }

    ModInt() {}
    ModInt(int val) : val(norm(val % P)) {}
    ModInt(i64 val) : val(norm(val % P)) {}

    bool constexpr operator <  (const ModInt &rhs) const { return val < rhs.val; }
    bool constexpr operator == (const ModInt &rhs) const { return val == rhs.val; }
    bool constexpr operator != (const ModInt &rhs) const { return val != rhs.val; }

    ModInt &operator += (const ModInt &rhs) & { return val = norm(val + rhs.val), *this; }
    ModInt &operator -= (const ModInt &rhs) & { return val = norm(val - rhs.val), *this; }
    ModInt &operator *= (const ModInt &rhs) & { return val = 1ll * val * rhs.val % P, *this; }
    ModInt &operator /= (const ModInt &rhs) & { return *this *= rhs.inv(); }

    ModInt constexpr operator + (const ModInt &rhs) const { ModInt ret = *this; return ret += rhs; }
    ModInt constexpr operator - (const ModInt &rhs) const { ModInt ret = *this; return ret -= rhs; }
    ModInt constexpr operator * (const ModInt &rhs) const { ModInt ret = *this; return ret *= rhs; }
    ModInt constexpr operator / (const ModInt &rhs) const { ModInt ret = *this; return ret /= rhs; }

    friend std::istream& operator >> (std::istream& is, ModInt &rhs) {
        i64 val; is >> val;
        return rhs.val = norm(val % P), is;
    }
    friend constexpr std::ostream& operator << (std::ostream& os, const ModInt &rhs) { 
        return os << rhs.val; 
    }
};

const int M = 998244353;
using Z = ModInt<M>;

void solve(){
    int n; std::cin>>n;
    std::vector<std::vector<int>> d(n);
    std::vector<int> fa(n);
    fa[0]=-1;
    std::vector<int> l(n);
    l[0]=0;
    for(int i=1,x;i<n;i++){
        std::cin>>x;
        x--;
        fa[i]=x;
        l[i]=l[x]+1;
        d[x].push_back(i);
    }
    std::vector<int> p(n);
    std::iota(p.begin(),p.end(),0);
    std::sort(p.begin(),p.end(),[&](int x,int y){
        return l[x]<l[y];
    });
    std::vector<Z> f(n);
    std::vector<Z> laysum(n,0);
    for(int x:p){
        if(x==0||fa[x]==0){
            f[x]=1;
            laysum[l[x]]+=1;
        }else{
            f[x]=laysum[l[x]-1]-f[fa[x]];
            laysum[l[x]]+=f[x];
        }
    }
    Z res=0;
    for(auto x:f) res+=x;
    std::cout<<res<<'\n';
}


signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    std::cin >> t; 
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}

智乃的“凑数”题(Easy Version)

https://ac.nowcoder.com/acm/contest/103957/E

思路:双重01背包

一道不错的背包题。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int mod = 998244353;
const int N = 105;

int n,m,a[N];
int dp[N][N],pre[N][N];

void query(int q){
    for(int i=1;i<=ceil(sqrt(q));i++){
        if(q%i!=0)continue;
        if(dp[i][q/i]){
            std::vector<int> vx,vy;
            int x=i,y=q/i;
            while(x!=0||y!=0){
                if(pre[x][y]>0){
                    vx.push_back(pre[x][y]);
                    x-=pre[x][y];
                }else{
                    vy.push_back(pre[x][y]*(-1));
                    y+=pre[x][y];
                }
            }
            std::cout<<"Yes\n";
            std::cout<<vx.size()<<' '<<vy.size()<<'\n';
            for(auto e:vx) std::cout<<e<<' ';
            std::cout<<'\n';
            for(auto e:vy) std::cout<<e<<' ';
            std::cout<<'\n';
            return;
        }
    }
    std::cout<<"No\n";
}

void solve(){
    dp[0][0]=1;
    std::cin>>n>>m;
    for(int i=1;i<=n;i++)std::cin>>a[i];
    for(int i=1;i<=n;i++){
        for(int x=100;x>=0;x--){
            for(int y=100;y>=0;y--){
                if(dp[x][y])continue;
                if(x>=a[i]&&dp[x-a[i]][y]){
                    dp[x][y]=1;
                    pre[x][y]=a[i];
                }else if(y>=a[i]&&dp[x][y-a[i]]){
                    dp[x][y]=1;
                    pre[x][y]=a[i]*(-1);
                }
            }
        }
    }
    while(m--){
        int x;std::cin>>x;
        query(x);
    }
}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}
posted @ 2025-03-21 15:43  califeee  阅读(3)  评论(0)    收藏  举报