计蒜课 八月模拟赛题解

看见机房有大佬上周写了上面的普及信心赛 于是我康了康 8月的提高组模拟赛 9月的还没开始qwq

真的 有点难 主要是我先打开了T2 我再次 对自己的数学产生了怀疑 我现在还是不会写T2

T1 又又又又都错题了 下次重建图 尽量写vector 都写 邻接表 变量差不多的容易搞混 我这个同学变又写错了

T1 :https://nanti.jisuanke.com/t/41086

题目大意就是 一个有向图 删一个点 把与他直接和间接 相连的点 删掉 然后 求删掉所有点的最小最大代价 ;

为了避免这个环的情况 我们显然是先 tarjan 求一下强连通分量 然后考虑 缩点 显然是删掉这个强连通分量的任意一个点 这个强连通分量都会被删掉

但是题目要求我们求出最大最小代价 那我们在求tarjan的过程中 维护每一个块的最大最小代价

那么对于最小代价 显然是缩点之后入度为0的节点的代价的累和

对于最大代价 我们反向建图 从叶子结点往上便利 然后每一个连通块的最大代价 累和 即可

#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
template<typename T>inline void read(T &x) {
    x=0;T f=1,ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    if(ch==‘-‘) f=-1, ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}
const int N=250000;
int n,m,x,y,cnt=0,ans1,ans2,num,tot,tc,top;
int in1[N],in2[N],Stack[N],minn[N],cost[N],maxx[N],dfn[N],low[N],lin[N],linc[N],ins[N],belong[N];
struct gg {
    int y,next;
}a[N],e[N];
inline void add(int x,int y) {
    a[++tot].y=y;
    a[tot].next=lin[x];
    lin[x]=tot;
}
inline void add_c2(int x,int y) {
    e[++tc].y=y;
    e[tc].next=linc[x];
    linc[x]=tc;
}
inline void tarjan(int x) {
    dfn[x]=low[x]=++num;
    Stack[++top]=x; ins[x]=1;
    for(int i=lin[x];i;i=a[i].next) {
        int y=a[i].y;
        if(!dfn[y]) {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(ins[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x]) {
        ++cnt;
        int k;
        do {
            k=Stack[top--];
            ins[k]=0;
            belong[k]=cnt;
            minn[cnt]=min(minn[cnt],cost[k]);
            maxx[cnt]=max(maxx[cnt],cost[k]);
        }while(x!=k);
    }
}
inline void topsort() {
    queue<int>q;
    for(int i=1;i<=cnt;i++) if(!in2[i]) q.push(i);
    while(q.size()) {
        int x=q.front();ans2+=maxx[x]; q.pop();
        for(int i=linc[x];i;i=e[i].next) {
            int y=e[i].y;
            in2[y]--;
            if(!in2[y]) q.push(y);
        }
    }
}
int main() {
    //freopen("1.in.cpp","r",stdin);
    read(n); read(m);
    for(int i=1;i<=n;i++) read(cost[i]),minn[i]=inf,maxx[i]=-inf;
    for(int i=1;i<=m;i++) {
        read(x); read(y);
        add(x,y);
    }
    for(int i=1;i<=n;i++) {
        if(!dfn[i]) tarjan(i);
    }
    for(int i=1;i<=n;i++) {
        //cout<<maxx[i]<<endl;
        for(int j=lin[i];j;j=a[j].next) {
            int y=a[j].y;
            if(belong[i]!=belong[y]) {
                //add_c(belong[i],belong[y]);没必要建图了;
                add_c2(belong[y],belong[i]);
                in1[belong[y]]++;
                in2[belong[i]]++;
            }
        }
    }
    ans1=ans2=0;
    for(int i=1;i<=cnt;i++)
        if(!in1[i]) ans1+=minn[i];
    topsort();
    printf("%d %d\n",ans1,ans2);
    return 0;
} 


T2 恶心数学题??? 原来只做过一个简化版的qwq 模拟赛当时考了 然后暴毙了;

那个模拟赛 我也没有写题解 那我在这里总结一下好吧 题目大意:

从(0,0)这个点 不跨过 y=x 和 y=x-(n-m) 到达(n,m)的方案数 保证 n>=2m

显然需要用不考虑跨过任何一条直线的方案数-跨过某一条直线的方案数*2+跨过两条的方案数;

总的方案数 $\tbinom{n+m}{m}$

然后考虑 跨过某一条直线的方案数 $\tbinom{n+m}{m-1}$

因为题目保证n>=2m 所以跨过第二条直线的时候 就没有机会跨过第一个了qwq 所以一定是 先跨过第一条线 在跨过第二条线

用和卡特兰数类似的方法也能求出来 方案数 $\tbinom{n+m}{m}$-$\tbinom{n+m}{m-1}$*2+$\tbinom{n+m}{m-2}$



这个T2 就比较恶心了 目标就是求从 (0,0)走到 (n,m)  且不经过 y=x+a 和 y=x+b 这两条的方案数,模数为 998244353 。

考虑 怎么做呢 其实 我的思路也是在不断 订正的 我第一遍看到 不会写 只会分类讨论 但是 刘神 指导说 应该是有通解的

那么我们不妨一点一点思考 讨论一下 这种组合数求解 这种问题的方法 需要几个简单例子的引入



如果 给定 (n,m) 和一个点 p(a,b) 只能往右 往上走 求出 不经过这个点p 到达终点 的方案数

那么我们也是用所有的方案数 减去 经过 p的 方案数

总的方案数 $\tbinom{n+m}{m}$ 然后考虑 一定经过p的方案数 那么我们先从(0,0) 走到 (a,b) 的方案数  再求出 (a,b) 走到(n,m)的方案数 这样我们显然

可以推出 方案数为$\tbinom{n+m}{m}$-$\tbinom{a+b}{b}$*$\tbinom{m+n-a-b}{n-a}$

原文地址:https://www.cnblogs.com/Tyouchie/p/11577290.html

时间: 2024-11-05 20:35:13

计蒜课 八月模拟赛题解的相关文章

[计蒜客NOIP模拟赛]2017.7.28Day1回顾反思总结

D1T1 打地鼠 题目链接 反思- 比赛得分-0 思考: 比赛时,以为T1是一道常规模拟题目,没怎么看数据范围.直接手动模拟,模拟完之后太自信也没有造数据Hack自己的程序.直接导致爆0.同时发现自己对二维前缀和的学习也只是在皮毛之上,没有深入思考与理解. 解题思路- 将图像旋转45°之后用二维前缀和维护,每次O(1)查询,时间复杂度O(N*N). 但是目前觉得这个图像旋转45°难以理解,打算手动模拟加深理解. 标程 #include<bits/stdc++.h> using namespac

计蒜客NOIP模拟赛4 D2T1 鬼脚图

鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线,且 在同一高度只会有一条横线. 在图的上方,我们将这 n 条竖线依次标号为 1 到 n.以数字 3 为例,它会沿着所在的竖线下降,期间如果 遇到横线就会移动到横线的另一端,最终降落至下面的第一条竖线.上图中还标出了另外几种数字的最终位置.奇特的是,开始时每条竖线上都有一个数字,而 最终每条竖线下还是

计蒜客NOIP模拟赛(3)D1T3 任性的国王

X 国的地图可以被看作一个两行 nn 列的网格状图.现在 X 国需要修建铁路,然而该国的国王非常小气,他只想保证位于某两列之间的所有城市互相可以到达就行了,在此基础上,他希望所花费的代价最小. 铁路可以建在任何两个相邻的点之间,使他们可以互相到达.可以作为工作人员,你已经整理出了为每一对相邻城市架设铁路所需要的花费.你需要准备好回答国王如下形式的问题. 对于 (i,j)(i,j):当前情况下,使第 ii 列到第 jj 列之间的所有城市连通的最小代价是多少(列下标从 11 开始)?注意不能用其他列

计蒜客NOIP模拟赛D2T3 数三角形

刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决.给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色.现在,洁洁需要给这张图的多样性进行打分.一张图的多样性取决于它的同色和异色三角形的个数.具体来说,G 中每有一个三边颜色都互不同的三角形(异色三角形)可以得 3 分,每有一个三边颜色都相同的三角形(同色三角形)则要被扣掉 6 分,其它三角形不得分也不扣分. 现在,请你写一个程序来计算 G 的多样性分数.输入格式 第一行两个正整数 n 和

计蒜客NOIP模拟赛(3) D1T2 信息传递

一个数据包在一个无向网络中传递.在时刻0,该数据包将依照特定的概率随机抵达网络中的某个节点.网络可以看做一张完全带权无向图,包含N个节点,若t时刻数据包在节点i,则在t+1时刻,数据包被传递到节点j的概率是 d(i,j)/(∑kd(i,k))其中d(i,j)表示节点i到节点j的最短路径的长度.在传递到下一个节点后,该数据包会自动删除在当前节点的备份.现在,给定数据包0时刻在每个节点的概率和网络的每条边权.求T时刻数据包在每个节点的概率.输入格式第一行两个整数N和T.第二行N个实数,表示0时刻数据

计蒜客NOIP模拟赛4 D1T2小X的密室

小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条从房间 X 到房间 Y 的通道.另外,想要通过某个传送门,就必须具备一些种类的钥匙(每种钥匙都要有才能通过).幸运的是,钥匙在打开传送门的封印后,并不会消失. 然而,通过密室的传送门需要耗费大量的时间,因此,小 X 希望通过尽可能少的传送门到达出口,你能告诉小 X 这个数值吗? 另外,小 X 有可能

计蒜客NOIP模拟赛4 D1T3 小X的佛光

小 X 是远近闻名的学佛,平日里最喜欢做的事就是蒸发学水. 小 X 所在的城市 X 城是一个含有 N 个节点的无向图,同时,由于 X 国是一个发展中国家,为了节约城市建设的经费,X 国首相在建造 X 城时只建造 N – 1 条边,使得城市的各个地点能够相互到达. 小 X 计划蒸发 Q 天的学水,每一天会有一名学水从 A 地走到 B 地,并在沿途各个地点留下一个水塘.此后,小 X 会从 C 地走到 B 地,并用佛光蒸发沿途的水塘.由于 X 城是一个学佛横行的城市,学水留下的水塘即使没有被小 X 蒸

计蒜客NOIP模拟赛4 D2T2 跑步爱天天

YOUSIKI 在 noip2016 的一道<天天爱跑步>的题爆零后,潜心研究树上问题,成为了一代大师,于是皮皮妖为了测验他,出了一道题,名曰<跑步爱天天>. 有一个以 1 为根的有根树,初始每个点都有个警卫,每个警卫会按深度优先的顺序周期性的巡逻以其初始点为根的子树(详见样例解释),一个时刻走且仅走一条边. YOUSIKI 初始在 x 点,他要到根结点拜访皮皮妖,他会沿着最短路径走,一个时刻走且仅走一条边,当他走到这个点时,如果遇到了警卫,他会消耗 1点妖气将这个警卫杀死,杀死后

复习---归并排序求逆序对--计蒜客2017noip模拟赛二--蒜头君的排序

题目链接:https://nanti.jisuanke.com/t/16443 我不会矩阵快速幂,所以只拿了60分, 发现归并排序掌握的并不熟练,借此良机复习一下. 重在归并排序分治思想,要牢记! #include<iostream> #include<cstring> using namespace std; int n,m,a[30005],s[30005],ans,d[30005]; void msort(int l,int r) { if(l==r)return;//如果只