首页 > 其他分享 >20240924 练习记录

20240924 练习记录

时间:2024-09-24 20:34:18浏览次数:7  
标签:cnt 记录 int text 练习 long else fa 20240924

3 个 DP,还想了几道题,但不会。

*P3349 [ZJOI2016] 小星星

考虑树上的点最终会对应在图上的哪个点,设 \(f_{x,i}\) 表示树上的点 \(x\) 对应图上点 \(i\) 时的方案数,当 \(x\) 对应 \(i\) 后,在树上 \(x\) 的所有子节点也必须像在树上一样,在图上和 \(i\) 之间有连边,有了这条限制,可以写出状态转移方程 \(f_{x,i} = \prod_{y\in\text{son}(x)}\sum_{j=1}^n f_{y,j}\times g_{i,j}\),其中 \(g\) 是图的邻接矩阵。

做到这里发现可能会有算重的部分,也就是说,树上有些点映射到图上的同一个点了,但是不要急着放弃,这个重复其实可以容斥掉!枚举所有点集合的子集 \(S\),然后强制只能映射到图上的这些点中。\(\text{popcount}(S)=n\) 时加答案,\(\text{popcount}(S)=n-1\) 的时候扣掉……以此类推。时间复杂度 \(\mathcal{O}(n^32^n)\)。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

// #define int long long

const int N = 20;

int n,m;

int g[N][N],_g[N][N];

vector<int> G[N];

long long ans, f[N][N];

void dfs(int x,int fa){
    for (int i = 1;i <= n;i++) f[x][i] = 1;
    for (int y : G[x]){
        if (y == fa) continue;
        dfs(y,x);    
        for (int i = 1;i <= n;i++){
            long long sum = 0;
            for (int j = 1;j <= n;j++)
                sum += 1ll * f[y][j] * g[i][j];
            f[x][i] *= sum;
        }
    }
}

signed main(){
    cin >> n >> m;
    for (int i = 1;i <= m;i++){
        int x,y; cin >> x >> y;
        g[x][y] = g[y][x] = 1;
        _g[x][y] = _g[y][x] = 1;
    }
    for (int i = 1;i < n;i++){
        int x,y; cin >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for (int S = 1;S < (1 << n);S++){
        memset(f,0,sizeof(f));
        for (int i = 1;i <= n;i++){
            if (!(S & (1 << (i - 1)))){
                for (int j = 1;j <= n;j++)
                    g[i][j] = g[j][i] = 0;
            }
        }
        dfs(1,0);
        long long res = 0;
        for (int i = 1;i <= n;i++){
            if (S & (1 << (i - 1))){
                res += f[1][i];
            }
        }
        if (__builtin_popcount((1 << n) - S - 1) & 1)
            ans -= res;
        else ans += res;
        memcpy(g,_g,sizeof(g));
    }
    cout << ans;
    return 0;
}

P6419 [COCI2014-2015#1] Kamp

很恶心的换根 DP!注意到点 \(i\) 最终的答案是,\(i\) 到所有关键点路径并 \(\times2\) 然后扣去与所有关键点里最大的那个的距离。到这里其实就做完了,细节非常多!求子树外最远距离需要记录次大值这是经典套路,求路径并的时候,要讨论子树内子树外是否有关键点的情况,在代码中标注出来了。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 5e5 + 5;

int n,k,f[N],g[N],_g[N],h[N],_h[N],cnt[N]; bool v[N];

struct Edge { int y,z; };

vector<Edge> G[N];

void dfs(int x,int fa){
    if (v[x]) cnt[x]++;
    for (auto e : G[x]){
        int y = e.y, z = e.z;
        if (y == fa) continue;
        dfs(y,x);

        cnt[x] += cnt[y];

        if (cnt[y])                         // !
            f[x] += z + f[y];

        if (cnt[y]){
            if (g[y] + z > g[x]){
                h[x] = g[x]; _h[x] = _g[x];
                g[x] = g[y] + z; _g[x] = y;
            }
            else if (g[y] + z == g[x]){
                h[x] = g[y] + z; _h[x] = y;
            }
            else if (g[y] + z > h[x]){
                h[x] = g[y] + z; _h[x] = y;
            }
        }
    }
}

void dfs2(int x,int fa){
    for (auto e : G[x]){
        int y = e.y, z = e.z;
        if (y == fa){
            if (k - cnt[x] == 0) continue;  // !
            
            f[x] = f[y];

            if (cnt[x] == 0) f[x] += z;     // !

            if (_g[y] == x){
                if (h[y] + z > g[x])
                    g[x] = h[y] + z, _g[x] = y;
                else if (h[y] + z == g[x])
                    h[x] = h[y] + z, _h[x] = y;
                else if (h[y] + z > h[x])
                    h[x] = h[y] + z, _h[x] = y;
            }
            else{
                if (g[y] + z > g[x])
                    g[x] = g[y] + z, _g[x] = y;
                else if (g[y] + z == g[x])
                    h[x] = g[y] + z, _h[x] = y;
                else if (g[y] + z > h[x])
                    h[x] = g[y] + z, _h[x] = y;
            }
            continue;
        }
    }
    for (auto e : G[x]){
        int y = e.y, z = e.z;
        if (y == fa) continue;
        dfs2(y,x);
    }
}

signed main(){
    cin >> n >> k;
    for (int i = 1;i < n;i++){
        int x,y,z; cin >> x >> y >> z;
        G[x].push_back({y,z}), G[y].push_back({x,z});
    }
    for (int i = 1;i <= k;i++){
        int x; cin >> x;
        v[x] = 1;
    }
    dfs(1,0);
    dfs2(1,0);
    for (int i = 1;i <= n;i++)
        cout << f[i] * 2 - g[i] << '\n';
    return 0;
}

**[ARC108E] Random IS

思考的时候从思维固化了,一直从顺序 DP 的角度去思考,然后就爆了啊。如果固定住一个区间 \([l,r]\),那么区间外不管怎么选择,都不会影响到区间内的信息。那就可以考虑区间 DP。设 \(f_{l,r}\) 表示必须选 \(a_l,a_r\),区间 \([l,r]\) 内标记个数的期望,区间 \((l,r)\) 内有 \(cnt\) 个不错的。转移直接枚举中间点 \(k\),\(f_{l,r}=\dfrac{1}{k}\sum_{l<k<r,a_l < a_k < a_r}f_{l,k}+f_{k,r}+1\)。

这样时间复杂度是 \(O(n^3)\) 的,发现枚举过程中,\(l<k<r,a_l<a_k<a_r\) 是一个二维数点问题,于是可以固定下标,用权值树状数组求解,每次更新加入 \(f_{l,r}\) 即可。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 2e3 + 5, P = 1e9 + 7;

// #define int long long 

int n,a[N];

struct SZSZ{
    int c[N];

    void add(int x,int y){
        for (;x < N;x += x & -x) (c[x] += y) %= P;
    }

    int sum(int x){
        int y = 0;
        for (;x;x -= x & -x) (y += c[x]) %= P;
        return y;
    }

    int query(int l,int r){
        return (sum(r) - sum(l - 1) + P) % P;
    }
}t[N][3];

int qpow(int a,int b){
    int c = 1;
    for (;b;b >>= 1,a = 1ll * a * a % P)
        if (b & 1)
            c = 1ll * c * a % P;
    return c;
}

long long f[N][N];

signed main(){
    cin >> n;
    for (int i = 1;i <= n;i++)
        cin >> a[i], a[i]++;
    a[0] = 1, a[n + 1] = n + 2;
    for (int l = n;l >= 0;l--){
        for (int r = l + 1;r <= n + 1;r++){
            if (a[l] > a[r]) continue;
            int cnt = t[l][2].query(a[l] + 1,a[r] - 1);
            if (cnt)
                f[l][r] = 1ll * (t[l][0].query(a[l] + 1,a[r] - 1) + t[r][1].query(a[l] + 1,a[r] - 1)) * qpow(cnt,P - 2) % P + 1;
            t[l][2].add(a[r],1), t[l][0].add(a[r],f[l][r]), t[r][1].add(a[l],f[l][r]);
        }
    }
    cout << f[0][n + 1];
    return 0;
}

*\(\color{red}{\text{[ARC184D] Erase Balls 2D}}\)

想了很久还是不会。

*\(\color{red}{\text{CF708E Student's Camp}}\)

想到了和一篇题解类似的做法,但只会用一次的前缀和优化,再往后晕了,先咕着明天写。

标签:cnt,记录,int,text,练习,long,else,fa,20240924
From: https://www.cnblogs.com/y1wei/p/18429955

相关文章

  • 化学套卷练习记录
    目录化学套卷练习记录202412024.9.202024苏州期初——【考试】59/7522024.9.242023年4月石家庄二模——【练习】58化学套卷练习记录202412024.9.202024苏州期初——【考试】59/75【总结】待upd【传送门】https://www.bilibili.com/video/BV15wsme5ELC22024.9.242023......
  • 封装的练习题目1
    1.使用面向对象的思想,编写自定义描述狗的信息。设定属性包括:品种,年龄,心情,名字;方法包括:叫,跑。要求:1)设置属性的私有访问权限,通过公有的get,set方法实现对属性的访问2)限定心情只能有“心情好”和“心情不好”两种情况,如果无效输入进行提示,默认设置“心情好”。3)设置构造......
  • 数据库练习
    1、查询所有学生信息,显示的内容包含:编号,姓名,班级,性别,出生日期,年龄,成绩SELECTid,NAME,clazz,gender,score,bir,TIMESTAMPDIFF(YEAR,bir,NOW())ageFROMinfo;2、查询每个班的学生人数各有几人SELECTclass,COUNT(*)ASstudent_numberFROMinfoGROUPBYclass;......
  • 【Day20240924】05git 两人协作 冲突
    git两人协作冲突命令行解决两个人修改同一文件时的冲突可视化解决两个人修改同一文件时的冲突参考命令行解决两个人修改同一文件时的冲突假设kerwin.js是项目的路由文件。tiechui文件夹是组员铁锤的工作目录;test2008文件夹是组长的工作目录。此时,两人都想要......
  • 微信聊天记录恢复最新恢复小技巧!
    微信在日常聊天记录中存有许多重要的数据,如工作文件、转账记录、视频照片等。这些聊天记录既便于日常工作的复盘,也能作为珍贵的聊天记忆保存在微信上。但是,如果我们不小心把微信删了,那聊天记录需要怎样恢复呢?针于对这个问题,在这里小编给大家总结了几点,帮助大家恢复微信聊天记录......
  • 打靶记录18——narak
    靶机:https://download.vulnhub.com/ha/narak.ova推荐使用VMWare打开靶机难度:中目标:取得root权限+2Flag攻击方法:主机发现端口扫描信息收集密码字典定制爆破密码Webdav漏洞PUT方法上传BF语言解码MOTD注入CVE-2021-3493提权主机发现arp-scan-l尝......
  • Drive.js 的一些 Api 使用记录
    文章目录2024年drive.js的基础使用想在下一步的时候处理些逻辑呢?(同步)Element的各种选择器2024年drive.js的基础使用安装就跳过了npminstalldriver.js,一行代码就可以搞定官网的BasicUsage基础使用的截图如下:想在下一步的时候处理些逻辑呢?(同步)......
  • E33.【C语言】数据在内存中的存储练习集(未完)
    1.求下列代码的打印结果#include<stdio.h>intmain(){ chara=-1; signedcharb=-1; unsignedcharc=-1; printf("a=%d,b=%d,c=%d",a,b,c); return0;}答案速查分析之前讲过,char在VS中默认为signedchar,则a和b的打印结果应该是一样的存储范围:si......
  • 第二天:Java练习
    1,BMI体质指数测试BMI=体重(kg)/(身高*身高),接收输入的身高和体重,然后输出结果:过轻:低于18.5正常:18.5~22.9偏胖:23~24.9肥胖:25~29.9重度肥胖:高于30packagejava4;importjava.util.Scanner;publicclasspractise{publicstaticvoidmain(String[]args){......
  • nodejs child_process 操作git 提交记录 提取git commit信息
    /***记录发布时的commit信息,用于区分内网版本包之间的差异*/importpathfrom'path';import{writeFileSync}from'fs';import{execSync}from'child_process';letoutputFileName=process.argv[2];if(!outputFileName){outputFileNam......