vis

题解 [SHOI2014]概率充电器

不问归期 提交于 2019-11-30 05:14:13
前情提要:最近大佬们都在写题解,只有我在咕咕咕。QAQ;明明我都把flag写出来辣,dalao们没看见,然后就被嘲讽了,QAQ 洛谷 树形DP+期望(讲了两次,菜鸡的我才做QAQ) 首先,每个充电元件和电源之间的关系可以用一棵树来表示。通过 感性 分析可知,每个元件对于期望的贡献就是0/1。(进入状态就是1,否则就是0)。故而进入充电状态的元件的个数的期望就是元件进入充电状态的概率。 那么设元件进入充电状态的概率为${\large{p[]}}$,我们要求的就转化为${\large{\sum_{i=1}^np[i]}}$ 然后我们就开始设计状态来求解${\large{p[]}}$。 显然 我们可以知道,一个点被充电只有两种可能:自己被自己所在的子树(包括自己)充上,自己被自己的父亲充上 然后开始思考,,,,, 一万年之后 我们发现,如果设计的状态是被充上电的话,状态就很难写,所以我们决定把状态设为不会被充上电的概率,即 ${\large{f[]}}$不会被自己所在子树充上电的概率,${\large{g[]}}$不会被自己的父亲充上电的概率 同时我们设已知量导线导电的概率为${\large{val[][]}}$表示${\large{i->j}}$可以充电的概率。用${\large{q[]}}$表示自己被自己充上电的概率。 首先求看起来比较容易求的${\large{f[]}}$

9.20模拟考试

泄露秘密 提交于 2019-11-30 05:12:15
9.20 考试 (某窦老师的题) 表示以后不想看到这名字,肽毒瘤 T1 题意: 我们可以把供游艇航行的航道看作一条单行道,航道上 \(N+1\) 艘游艇自西 向东依次编号为 \(0..N\) ,小 Z 所在的游艇在最西边编号为 0,而编号为 \(N\) 的游艇 还要再往东航行一段才是小蛮腰。由于晚上航行视野不佳,排在后面的船不允 许超越前面的船,而当前面的船航行速度太慢时,后面的船只能以相同的速度 紧跟着,此时两船之间的距离可以忽略。 已知第 i 艘游艇船身长为 \(L[i]\) ,船头与小蛮腰距离为 \(X[i]\) ,最大航行速 度为 \(V[i]\) 。小 Z 好奇,他到底要等多久,才能乘着游艇经过小蛮腰脚下呢? ​ 反思: 考场上先是想了贪心(显然是不对的),,又推了DP, $f_i=max(X_i/V_i, f_{i+1}+L_{i+1}/V_{i+1}) $ 最后的时候发现好像也是不对的,没有考虑过线后其实也在堵着。。。然后就凉了; 倒是 \(yych\) ,很涩会,机房唯一一个切此题的人%%%%% 正解是实数域上二分: 可以看出答案是具有单调性的, 所以我们可以二分一个时间,判断它成不成立。 设 \(dis =tim*V_i\) \(lin_i\) 为 \(tim\) 时间后第 \(i\) 个船离小蛮腰还有多久 则就有dp : \(lin[i]=max(lin[i]

AtCoder Grand Contest 014题解

 ̄綄美尐妖づ 提交于 2019-11-30 04:16:41
传送门 \(A\) 首先大力猜测一下答案不会很大,所以次数大于 \(10^6\) 输出 \(-1\) 就行了 不过我并不会证上界,据说是因为如果 \(a=b=c\) 且都是偶数肯定 \(-1\) ,否则设 \(a\leq b\leq c\) ,则最大最小值的差为 \(c-a\) ,一次操作之后变成了 \({c-a\over 2}\) ,所以操作次数就是 \(\log\) 级别的了 typedef long long ll; ll a,b,c,sum;int res; int main(){ scanf("%lld%lld%lld",&a,&b,&c); sum=a+b+c; while(true){ if((a&1)|(b&1)|(c&1))return printf("%d\n",res),0; a=(sum-a)>>1,b=(sum-b)>>1,c=(sum-c)>>1; if(++res>1e6)return puts("-1"),0; } return 0; } \(B\) 既然题目要求每条边被覆盖偶数次,那么一定可以被拆分成若干个联通边集且这个边集里每条边都被覆盖 \(2\) 次,而这个边集肯定形如若干条 \((a_1,a_2),(a_2,a_3),...,(a_n,a_1)\) 的路径的并,再转化一下就是在新图中将 \((u,v)\) 连边

棋盘问题 (北京大学ACM-ICPC竞赛训练暑期课 )

╄→尐↘猪︶ㄣ 提交于 2019-11-30 03:36:07
描述在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。输入输入含有多组测试数据。 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n 当为-1 -1时表示输入结束。 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。 输出对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。样例输入 2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1 样例输出 2 1 #include <bits/stdc++.h> using namespace std; int n,k,ans=0,cnt=0; int vis[9]; string str[9]; void DFS(int h) { if(ans==k) { cnt++; return ; } if(h>=n) return ; for(int i=0;i<n;i++) { if(str[h][i]=='#' && !vis[i]) { vis[i]=1; ans++;

P2664 树上游戏 点分治

早过忘川 提交于 2019-11-30 03:33:37
   树上点对问题很容易就想到点分治 点分治已经用掉一个log了 那么我们的问题就转化为: 在 o(n) 时间内求出 以该根为lca的所有的点对的答案! 1、对于树上的一个i 如果i的颜色在i到根的链上是第一次出现 那么可以对树上其他的点j (不考虑特殊情况)产生贡献siz[i] (j与子树i的每一个点都产生贡献1) 2、dfs求出sum(整棵树所有的贡献 和color[i] 这个颜色所有的贡献) 3、显然 根的答案为 ans[root]+=sum 也就是一端在根上的链 4、遍历子树 统计答案   但是有一些不是树上最短路径的贡献不能被统计进去 所以要在该子树统计答案的时候 删除该子树的影响 然后再回溯回去 5、设X=sigma color[j 到根上(不包括根)的所有颜色] 由于这些颜色已经出现过,我们不能在该子树外计算其贡献)   设num为j到根上(不包括根)的颜色数   设Y为size[root]-size[该子树](即所有其他子树+根的点数)   则ans[j]+=sum-X+num*Y; 这样一道黑题就大功告成啦 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b)

记忆化搜索

两盒软妹~` 提交于 2019-11-30 02:58:16
直接上题: 本题就是求在m的情况下,那些点能通过吃其他的点,强化自己然后留到最后(挺像大鱼吃小鱼的)。 没错,这就是挂我暴力的题,本来50分的暴力,因为没开longl long只剩可怜的十几分,算了,长个教训吧! 我们刚开始的思想就暴力呗!暴力检查每个点能否扩到最后,然后输出! 显然非正解... 显然最大的点一定是必胜点,那我们再深入思考,必胜点都有什么性质:假如a是必胜点,而b再加强一部分后能吃掉a,那b显然也一定是必胜点! 之后我们再考虑一个点x可以没有m限制的区间,那就是左右两边第一个比m大的数。 没有m,x依然可以在这个区间里随便吃,知道碰到第一个比他大的数,需要验证了。 如果设想p,q分别为第一个比m大的数,如果p是必胜点,而x能吃掉p,那显然x也是必胜点; 可如果p不是必胜点呢?x也一定不是必胜点,为什么呢?因为p比x大而检查p时也一定加上x的那个区间,但p不是必胜点,则x也一定不是必胜点了。 这样一个数的判断依赖于左右两个点的判断,即想知道x,必须知道p,q;这样搞一个记忆化搜索,就可以O(n)求解了。 #include<bits/stdc++.h> #define ll long long using namespace std; const ll N=8100000; ll n,m,a[N],vis[N],l[N],r[N],top,maxx,sum[N];

1087Dijkstra+DFS

这一生的挚爱 提交于 2019-11-30 02:40:34
初始思路:问题所在 //思路:Dijkstra算法,找最短路径, 点权:最大,如果多种,则给出平均点权最大的路径。 //实现:字符串对应编号处理;————————终点是ROM————记录。 // 求最大happy————满足路径上的传递————最优子结构: //要求:记录中间路径, 记录最短路径数目。 //补不足:边权点权的初始化,递推 //改正:彻彻底底弄清题意:cost最少的路径,多条则happy总和最大, //多条则路径的平均距离最小--->保证最小。------->所以DFS实现。 //1003---->对比 # include <bits/stdc++.h> # define MAXN 205 # define inf 0x3fffffff using namespace std ; int e [ MAXN ] [ MAXN ] , d [ MAXN ] , happy [ MAXN ] , h [ MAXN ] , num [ MAXN ] ; vector < int > path ; bool vis [ MAXN ] ; int n , k , nummember ; map < int , string > is ; map < string , int > si ; int change ( string s ) { if ( si . find ( s )

图论算法总结(一)——图的遍历

点点圈 提交于 2019-11-30 02:22:00
图论算法总结 一、前言 关于数据结构,主要是有关树和图是最终的难点和痛点,关于算法,记住名字很简单,记住原理要花一点时间,如何内化为自己本身的知识,以及,在脑中有思路,随拿随用,这个需要特定的记忆方式。如果不能即拿即用,并不能说自己了解这个算法。建议大家,以自己的思维为中心,记住该思维的逻辑的同时,也记住该思路的代码,把算法内化为自己的修养。 参考博文: https://liuchuo.net/archives/tag/dfs(与原博文有一定差异,建议大家也按照自己思路进行书写代码,每个人思维方式不一样 ) 二、图的遍历 2.1.深度优先dfs遍历图 按照深度优先方式访问未访问的节点 2.1.1.伪代码 dfs(u){ vis[u]=true; for(从u出发能到达的所有顶点v) if(vis[v]==false) dfs(v); } dfsTrave(G){ for(G的所有节点u) if(vis[u]==false) dfs(u) } 2.1.2.C语言代码(邻接矩阵) //邻接矩阵 void dfs(int u){ vis[u]=1; printf("%d",u); for(int i=0;i<vertxNum;i++) if(vis[i]==0&&path[u][i]==1) dfs(i); } void dfsTrave(){ for(int i=0;i

P4149 [IOI2011]Race 点分治

孤人 提交于 2019-11-30 02:06:59
  题意:给定一棵有边权的树 和一个k 问最少多少边(连续)的长度和为k 解法一(也是我一开始的写法) 遍历所有的边 并且给每个边设置一个标记属于某课子树 然后用lowerbound和upperbound找到满足的边 遍历一遍统计答案 用了4s 解法二(只用2s) 边数太多的时候上面的算法复杂度接近 n^2logn QAQ 可以做成3n的 并且每一棵每一棵子树得统计答案和更新子树情况 (先统计 后更新) 就可以避免统计的边不是最短路的情况 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////////// const int N=2e5+10; int n,m,cnt,d[N],head[N],pos,siz[N],sum,x,y,z,ans,vis[N]

codeforces 1213D2 Equalizing by Division (hard version) 贪心+暴力

こ雲淡風輕ζ 提交于 2019-11-30 00:28:58
http://codeforces.com/problemset/problem/1213/D2 题目大意:给 n n n 个数,每一次操作可以任意选择一个数 a i a_{i} a i ​ ,使 a i = a i / 2 a_{i}=a_{i}/2 a i ​ = a i ​ / 2 (向下取整)。问至少需要多少次操作才能使得序列中有 k k k 个相等的数。 思路:排序后暴力计算贡献就行了。设 v i s [ i ] vis[i] v i s [ i ] 表示有多少个等于 i i i 的数,设 a n s [ i ] ans[i] a n s [ i ] 表示得到 v i s [ i ] vis[i] v i s [ i ] 个 i i i 最少需要多少次操作,那么对于 a i a_{i} a i ​ ,一直做除2操作,同时更新 v i s [ i ] vis[i] v i s [ i ] 和 a n s [ i ] ans[i] a n s [ i ] ,最后遍历 v i s vis v i s 序列找到满足 v i s [ i ] > = k vis[i]>=k v i s [ i ] > = k 的最小的 a n s [ i ] ans[i] a n s [ i ] 即可。注意一定要先对序列从小到大排序。(贪心思想) # include <iostream> #