• 7月、8月考试总结(1)


    7.10: Test1 惨遭爆零 TAT

       第一题 在本地测是过了的  到了教师机莫名输出0 ??   一道spfa的板子题  还做过 WA了也就GG。。[POJ2502]Subway

       后来发现了  结构体强转有大问题????  woc

       第二题 听大佬讲 有三种方法

      1是floyd判一下 f[x][y] ?= f[x][k] + f[k][y] 还标记个flag(是否存在); 

      2是一个spfa找负环 这需要建一个神奇的图;

      3是一个诡异的贪心  (左端相等 减去左边相等的数 再加入优先队列 如果区间相等 判断数是否相等 不相等就false)。

      反正我都没想到  (难道高斯消元+区间离散 不能做?? 到时候再研究)洛谷【P2294】[HNOI2005]狡猾的商人 

         后来点开标签看了看 原来是差分约束(虽然原来好像讲过,但根本不记得了) 去网上找了篇好博文 终于懂了

       第三题 一道强联通分量缩点 + 树形(DAG)dp  没时间写了 也只好GG    洛谷【P3436】[POI2006]PRO-Professor Szu

       总结:先做思路更明显的题  程序注意细节  不要瞎搞  再接再厉 明天继续 fighting


    7.12:Test2 130分。。(一般人拿的分qwq)

      第一题 一道求解涂色方案数问题 判是否可行 看到就一脸懵 以为又是一道数学找规律题 草草地打完了爆搜就没去动了 后来回头想来写dp没写出来QAQ

      正解是矩阵快速幂(膜一波hy大大   构造一个可行型矩阵,乘自己n-1次(用快速幂做),最后再乘上dp矩阵) 还有种神奇方法 倍增思想来做dp  两种时间复杂度差不多都是O(log n)

      第二题 一道trie的裸题,但是数据卡trie,我就竟然奇迹般地写出了hash(似乎还是正解) 竟然时间效率还不错。以后要多多练练hash。 [HDU1075]What are you talking about?

          第三题  一道拓欧的题,不知道拓欧咋写,又咋去用。。。 反正不太会QAQ。。 后来听了几位大牛的讲解  终于搞懂了qwq。。 [POJ2155]C Looooops

      总结:有时候脑洞还是要开大一点 有可能灵机一闪的思路是正解


    7.13:Test3 200分 (数据太水了。。。正解基本没过。。暴力还有a+b都能AC TAT)

      第一题 一道平面几何题 计算任意两点之间距离的最大值 暴力全部秒过= = 正解是先做一遍凸包 把凸包上的点保留 再做一遍暴枚[POJ2187]Beauty Contest  

      第二题 一道求最大团的题(一开始不知道 写了个点枚暴力复杂度O(n^2 * 2^n)特别高QAQ)后来才知道是一道NP难问题(NPC)GG第一次碰   可以用Bron–Kerbosch算法(但好像会TLE)其实根据这道题的特殊性

      可以把原图延伸为一个补图(将所有原图原本存在的边删掉加上不存在的边)然后跑一边二分图最大匹配 这样就可以把原图中互相不认识的一些点删掉 最后答案就是nl+nr-res [POJ3692]Kindergarten      

      第三题  一道搜索剪枝的题 (考试时候剪枝剪多了WA了 TAT) 有一个玄学剪枝 就是(maxv - sumv) / r * 2 + sums >= ans 这个就将体积换成侧面积来计算接下来的最大面积 这个似乎优化很多

           一开始改了很久 发现枚举高度时 不能直接从h-1开始 有时要从(maxv-sumv-minv[deep-1]) / (i*i)(可用体积除以半径)开始 就是两个的最小值   [POJ1190]生日蛋糕

     


    7.14:Test4 170分 (这次比较正常。。发挥刚好。)

      第一题 一道最长不上升和不下降的裸题 不能用O(n^2)的算法来做 (n=100000) 要用 二分当前最优解的方法去写。 有点类似于合唱队型。。洛谷【P1091】合唱队形

      第二题 一道特殊的01背包 考试没看出来(因为是乘积)最后只好写了一个DFS 去搜索 结果挂了 只有20分TAT  其实就是按减少饥饿值从大到小排序 如果当前减少饥饿值为负数 就不算 否则就更新f[i](i表示减少饥饿值为i时 最大的战斗力) 最后线性扫一遍就行了 [POJ2184]Cow Exhibition

            第三题  又是一道报复社会的数论题。。 就是筛素数  要用上一种特殊的筛法 Miller-Rabin   这个就需要一些数论基础了  而且为了防爆范围 需要取模乘(类似于快速幂) 而且还需要一个快速幂来计算   这个运用了费马小定理 还有 二次探测定理  [POJ1811]Prime Test


     

    7.18:Test5 50分 (TAT倒数第四(还有小朋友) 要被丢出去了)

      第一题 一道搜索贪心 或者 递推dp  太自信了 5min打完就做后面了 没认真看看TAT

      第二题 一道神奇的贪心 将根节点能选的最多节点数计算出来(sum) 再计算出从大到小sum个数的和再加起来。。。没想出来TAT

      第三题  这道题就也是报复社会了。。。暴力打挂了,flag前面特判错了QAQ。。。正解用线段树进行维护 十分复杂(可以媲美工业题了)  

       总结:真的要注重细节啊!!!!!  明天NOI同步赛了。。  争取拿分 沉下心来 好好弄!!!


     

    8.2:Test6 120分 (成功诠释暴力骗分的正确方法2333)  PS:以后开始附代码了(还有他们的解题报告。。)  

      第一题 一道神奇的图论题(我考试时并没有理解题目的真正含义,靠暴力三重循环竟然骗了40分0.0)正解是类似于DAG dp,就是计算每一个点能到达的节点个数,因为能到达的节点必须要扩充边。需要用bitset来维护这个集合,可以进行数位优化,除以一个ω。为了防止爆空间,所以跑两遍。。(dy的程序是真的强,十分精炼……)

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <bitset>
     7 using namespace std;
     8 #define For(i, l, r) for(int i = (l), _end_ = (int)(r); i <= _end_; ++i)
     9 #define Fordown(i, r, l) for(int i =(r),_end_ = (int)(l); i >= _end_; --i)
    10 #define Set(a, v) memset(a, v, sizeof(a))
    11 
    12 inline int read() {
    13     int x = 0, fh = 1; char ch;
    14     for(; !isdigit(ch); ch = getchar()) if(ch == '-') fh = -1;
    15     for(; isdigit(ch); ch = getchar()) x =(x<<1) + (x<<3) + (ch ^ '0');
    16     return x * fh;
    17 }
    18 
    19 const int N = 60100, M = 100100;
    20 int to[M], Next[M], Head[N], e = 0;
    21 void add_edge (int u, int v) {
    22     to[++e] = v;
    23     Next[e] = Head[u];
    24     Head[u] = e;
    25 }
    26 
    27 bitset<N/2> G[N];
    28 bool vis[N];
    29 int n, m, ans = 0;
    30 void dfs (int u, bool flag) {
    31     if (vis[u]) return;
    32     vis[u] = true;
    33     if (flag && u <= (n>>1) ) G[u][u] = true;
    34     else if (!flag && u > (n>>1) ) G[u][u - (n>>1)] = true;
    35     for (int i = Head[u]; i; i = Next[i]) {
    36         int v = to[i];
    37         dfs (v, flag);
    38         G[u] |= G[v];
    39     }
    40     ans += G[u].count();
    41 }
    42 
    43 int main(){
    44     freopen ("worldline.in", "r", stdin);
    45     freopen ("worldline.out", "w", stdout);
    46     n = read(); m = read();
    47     For (i, 1, m) {
    48         int u = read(), v = read();
    49         add_edge (u, v);
    50     }
    51     For (i, 1, n) dfs (i, true);
    52     Set(vis, false);
    53     For (i, 1, n) G[i].reset();
    54     For (i, 1, n) dfs (i, false);
    55     printf ("%d
    ", ans - n - m);
    56     return 0;
    57 }
    View Code

      第二题 一道看起来是道网络流,其实是一道贪心的题目0.0(题目把我们带走远了,dy出题真的强……)就是将左节点排序,然后去从左至右,一个个贪心去比较,维护序列用map或者set……(不得不说dy的STL也用的出神入化,不愧是进队爷……QAQ)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define For(i, l, r) for(int i = (l), _end_ = (int)(r); i <= _end_; ++i)
    #define Fordown(i, r, l) for(int i =(r),_end_ = (int)(l); i >= _end_; --i)
    #define Set(a, v) memset(a, v, sizeof(a))
    
    inline int read() {
        int x = 0, fh = 1; char ch;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') fh = -1;
        for(; isdigit(ch); ch = getchar()) x =(x<<1) + (x<<3) + (ch ^ '0');
        return x * fh;
    }
    
    const int N = 100100;
    struct node {
        int l, r, s;
        bool operator < (const node &rhs) const {
            return l < rhs.l;
        }
    };
    node a[N], b[N];
    int n, m;
    typedef long long ll;
    #include <map>
    map<int, ll> M;
    
    void solve() {
        int j = 1;
        For (i, 1, n) {
            for(;j <= m && b[j].l <= a[i].l; ++j) 
                if (!M.count(b[j].r) ) M[b[j].r] = b[j].s; 
                else M[b[j].r] += b[j].s;
            while (a[i].s) {
                map<int, ll>::iterator p = M.lower_bound(a[i].r);
                if (p == M.end() ) {puts("No"); return;}
                if (a[i].s < p -> second) {p -> second -= a[i].s; a[i].s = 0;}
                else {a[i].s -= p -> second; p -> second = 0; M.erase(p);}
                }
            }
        puts("Yes"); 
        return; 
    }
    
    int main(){
        int t = read();
        while (t--) {
            M.clear();
            n = read(); m = read();
            For (i, 1, n) 
                a[i] = (node) {read(), read(), read()};
            
            For (i, 1, m) 
                b[i] = (node) {read(), read(), read()};
            
            sort (a + 1, a + 1 + n);
            sort (b + 1, b + 1 + m);
            solve();
        }
        return 0;
    }
    View Code

      第三题 一道题面看了很久看懂,只会打杨辉三角暴力的,恐怖数论题……正解根本看不懂啊QAQ 数论还是太弱了……


     

    8.3:Test7 110分(再次成功诠释暴力出奇迹的神奇方法2333)

      第一题 一道概率题 原来从来都不会概率……被逼无奈 写了O(2^n)的暴力来推算……60分的概率dp O(n^2) 也有点难度,也不会QAQ……正解是O(n)的递推……要将递增的每一项对最后期望值的贡献求出来,最后还要将k对它的影响给表示出来……反正很变态= =

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1000000 + 10;
    
    int n, k;
    double P[maxn];
    double p, x, x2, y, ans;
    
    int main() {
    
        scanf("%d%d", &n, &k);
        for(int i = 0; i < n; i++) {
            scanf("%lf", &p); P[i] = p;
    
            ans += p * (3 * x2 + 3 * x + 1);
            x2 = p * (x2 + 2 * x + 1);
            x = p * (x + 1);
    
            ans -= (1.0-p) * (2 * y + 1);
            y = (1.0-p) * (y + 1);
        }
    
        ans += k * P[0] * P[n-1];
        ans -= k * (1-P[0]) * (1-P[n-1]);
    
        printf("%lf
    ", ans);
        return 0;
    }
    View Code

      第二题 一道看起来就不会做的题(事实上还是不会做),乘法逆元加上一个区间的变换……反正都不知道……TAT  只挂个正解的代码在上面吧

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int maxn = 500 + 5;
    const int mod = 998244353;
    
    int n, m;
    int a[maxn], d[maxn];
    
    LL S[maxn][maxn];
    LL dp[2][maxn][maxn], chs[maxn];
    
    #define ADD(a, b) ((a += b) >= mod ? a -= mod : a)
    #define NONE(i, j) (chs[i-1] + chs[n-j] + chs[j-i+1])
    
    LL fpm(LL base, LL exp) {
        LL ans = 1;
        for(; exp > 0; exp >>= 1) {
            if(exp & 1) 
                ans = ans * base % mod;
            base = base * base % mod;
        }
        return ans;
    }
    
    void calc(int l, int r, int pos) {
    
        bool cur = 1;
        for(int i = l; i <= r; ++i)
            for(int j = i; j <= r; ++j) dp[0][i][j] = 0;
    
        dp[0][l][r] = 1;
        static LL sum = 0;
    
        for(int t = 0; t < m; ++t) {
            LL (*now)[maxn] = dp[cur], (*lst)[maxn] = dp[cur^1];
    
            for(int i = l; i <= r; ++i)
                for(int j = i; j <= r; ++j) 
                    now[i][j] = lst[i][j] * NONE(i, j);
    
            for(int i = l; i <= r; ++i) {
                sum = 0;
                for(int j = r; j >= i; --j) {
                    now[i][j] = (now[i][j] + sum);
                    sum = (sum + lst[i][j] * (n-j));
                }
            }
            for(int j = r; j >= l; --j) {
                sum = 0;
                for(int i = l; i <= j; ++i) {
                    now[i][j] = (now[i][j] + sum) % mod;
                    sum = (sum + lst[i][j] * (i-1));
                }
            }cur ^= 1;
        }
    
        for(int i = l; i <= r; ++i)
            for(int j = i; j <= r; ++j) {
                ADD(S[i][pos], dp[cur^1][i][j]);
                ADD(S[j+1][pos], mod-dp[cur^1][i][j]);
            }
    }
    int main() {
        freopen("B.in", "r", stdin);
        freopen("B.out", "w", stdout);
    
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) chs[i] = i * (i+1) >> 1;
        for(int i = 1; i <= n; ++i) scanf("%d", a + i), d[i] = a[i];
    
        sort(d + 1, d + n + 1);
        for(int i = 1; i <= n; ++i) {
            int l = i, r = i;
            while(l > 1 && a[l-1] <= a[i]) --l;
            while(r < n && a[r+1] <= a[i]) ++r;
            calc(l, r, lower_bound(d + 1, d + n + 1, a[i]) - d);
        }
        
        for(int i = 1; i <= n; i++) 
            for(int j = 1; j <= n; j++) { ADD(S[i][j], S[i-1][j]); }
    
        LL INV = fpm(n * (n + 1) >> 1, LL (mod - 2) * m);
        for(int i = 1; i <= n; ++i) {
            LL ans = 0, tmp = 0;
            for(int j = 1; j <= n; ++j) if(S[i][j]) {
                ans = (ans + (S[i][j] - tmp) * d[j]) % mod;
                tmp = S[i][j];
            }
            ans = ans * INV % mod;
            printf("%lld
    ", (ans + mod) % mod);
        }
        return 0;
    }
    View Code

      第三题 一道我用暴力骗了90分的题目(Wearry良心出题人QwQ)

    正解是先求出dfs序,再用背包在上面跑,标程有些细节还是没看懂……引用wt大佬的博客算了……

    #include<bits/stdc++.h>
    using namespace std;
    
    void chkmax(int & a, int b) { if(a < b) a = b; }
    
    const int oo = 0x3f3f3f3f;
    const int maxn = 5000 + 10;
    const int maxm = 10000 + 10;
    
    int st[maxn], nxt[maxm], to[maxm], e = 1;
    void addedge(int u, int v) {
        to[++e] = v; nxt[e] = st[u]; st[u] = e;
        to[++e] = u; nxt[e] = st[v]; st[v] = e;
    }
    
    int dp[maxn][maxn]; //这个dp的第一维下标是更新后的dfs序 
    int n, m, dfs_clock;
    int dfn[maxn], efn[maxn];
    int id[maxn], p[maxn], d[maxn];
    
    void dfs(int u, int f = 0) {
        id[dfn[u] = ++ dfs_clock] = u;
        for(int i = st[u]; i; i = nxt[i]) 
            if(to[i] != f) dfs(to[i], u);
        efn[u] = dfs_clock + 1; //记录u节点能到的最远的儿子编号+1 即选这个节点的祖先节点 能选到的下一个点 
    }
    
    int main() {
        freopen("C.in", "r", stdin);
        freopen("C.out", "w", stdout);
    
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%d%d", d + i, p + i);
        for(int i = 1; i < n; ++i) {
            static int u, v;
            scanf("%d%d", &u, &v);
            addedge(u, v);
        }
    
        dfs(1);
    
        memset(dp, ~oo, sizeof dp);
        dp[1][0] = 0; //根节点不取时默认为0 
    
        int ans = 0;
        for(int i = 1; i <= n; ++i) {
            int u = id[i];
            for(int j = 0; j <= m; ++j) if(dp[i][j] >= -oo) { //负无穷更新其他的毫无意义…… 
                chkmax(ans, dp[i][j]); //更新当前答案的最大值 
                chkmax(dp[efn[u]][j], dp[i][j]);  //更新
                if(j + p[u] <= m) //如果还在容量之内 
                    chkmax(dp[i+1][j + p[u]], dp[i][j] + d[u]); //更新下一个(儿子或者efn)的背包 
            }
        }
        for(int i = 0; i <= m; ++i) chkmax(ans, dp[n+1][i]);
        printf("%d
    ", ans);
        
        return 0;
    }
    View Code

     8.3:Test8 5分(这个分数太恐怖了……题目有些BT……但我的暴力也没打好,细节没注意QAQ)

      第一题 一道二分答案加堆维护的题目……细节比较多……需要有些神奇思路,以及一些方法处理

      第二题 一道贼难的数论题……好不容易推出了暴力,结果还打错了TAT 正解运用的定理,我一个都不懂,以后要恶补数论了啊!!

      第三题 一道坑比的生成树题目……TAT 第一个点开始就要long long了  结果最大值开小了 GG了 正解也不懂 一个01 trie有些变态…… 20%的快速幂也没混到,贪了,数组小了TAT

      30分解法见大佬博客2333 hzwer


     

  • 相关阅读:
    [Erlang05]gen_server怎么去写eunit?
    [Erlang04]为什么有了rpc还有net_kernel:connect/1?
    [Erlang03]Erlang有哪些好用的静态分析工具?
    [SIP01]SIP Header Fields里面各字段用途
    [SIP00]SIP 概念总结
    [Erlang00]:gen_server:reply/2
    Makefile教程
    Linux 环境下开发 STM32
    Ubuntu 18.04 + ROS Melodic + TurtleBot3仿真
    Ubuntu系统鼠标不能点击
  • 原文地址:https://www.cnblogs.com/zjp-shadow/p/7147724.html
Copyright © 2020-2023  润新知