导航

8月上半刷题总结

Posted on 2025-08-27 10:22  tttfred  阅读(6)  评论(0)    收藏  举报

1.组合数学

排列组合

P5520 插空法——不相邻问题时的做法
P3323 分类讨论,考虑排男生、老师、女生的顺序,注意老师两个中间也可以插,分成老师本就不相邻和老师原本相邻,插进女生不相邻两种,高精度计算即可

容斥原理

P3197 问n个牢房,m个宗教,每个相邻房间若宗教相同则粤越狱。考虑两两不相邻,第一个有n种选择,后面的都有(n-1)种选择,n*(n(m-1)-(n-1)(m-1))快速幂求解即可

2.STL栈

rc-国赛-03删除屏蔽词

发现特殊之处在于屏蔽词两个字符,类比括号序列,()就消掉否则就不消,最后逆序输出栈即可。这种题一定要注意特殊条件,如天梯赛有一道不是字符串题,26个代号提示你将数字化为字母进而转化为字符串解题。

4.数论解题

很重要一点就是列算式,找特殊
P1445 很容易知道x,y>n! 但是,列出y=n!+k (k为正整数)消元不容易。继而找到x=(n!)^2/k+n! 然后发现就是求k的个数,应用约数个数定理即可

5.树

重要知识点:树上两点最近距离=Ro->a+Ro->b-R_o->lca(a,b)
求最近公共祖先应用dfs序码量最小,时常记

void dfs(int r, int f)
{
    for (int i = 1; i <= 20; i++)
    {
        if (i == c[r])
        {
            dp[r][i] = dp[f][i] + 1;
        }
        else
            dp[r][i] = dp[f][i];
    }
    st[dfn[r] = ++idx][0] = f;
    vis[r] = 1;
    for (int i = 0; i < edge[r].size(); i++)
    {
        int to = edge[r][i];
        if (!vis[to])
        {
            dfs(to, r);
        }
    }
}
int cal(int x, int y)
{
    return dfn[x] < dfn[y] ? x : y;
}
int lca(int x, int y)
{
    if (x == y)
        return x;
    else
    {
        if ((x = dfn[x])> (y = dfn[y]))
            swap(x, y);
        int t = log2(abs(x - y));
        return cal(st[x + 1][t], st[y - (1 << t) + 1][t]);
    }
}
`
//省略了st表建立部分,注意用cal代替min计算

差分

当出现段计数,常常要用到差分。比如天梯赛里面的胖达山头。就是用差分,选择重叠数最多的时间段;CF2014D,问一个d区间有多少种不同的线段(部分),稍微变一下,把左右界改到(max(0,l-d+1),min(n,r+d-1))即可

数位dp

求一段大区间的和也可以用数位dp,对计数值乘以数值即可,但是要注意常数问题,CF2132D,比赛时把【0,maxnum】拆成两个区间,因为常数问题就超时了。