[HNOI2011]XOR和路径 && [HNOI2013]游走
[HNOI2011]XOR和路径
题目大意
具体题目:戳我
题目:
给定一个n个点,m条边的有重边、有自环的无向图,其中每个边都有一个边权。
现在随机选择一条1到n的路径,路径权值为这条路径上所有边权的异或和。
特别注意,如果同一条边在路径中经过了多次,那么路径权值也要异或对应次数的边权。
请回答 这条路径的 期望权值 为多少。
数据范围:\(n \leq 100\) , \(m \leq 10^4\) 。对于所有边,\(val_E \leq 10^9\)。
思路及解法
A
首先,求异或问题拆成每一个二进制位来算这都是老套路了。
本题也是一样,把每一个边权拆成二进制的每一位。
那么此时我们只用考虑这一位为\(1\)的概率,最后贡献乘上一个对应系数即可。
倒着\(DP\) , 设\(f[u]\)表示\(u\)到\(n\)路径异或和为\(1\)的概率。
转移还是挺简单的:
\[f[u] = \sum \frac{f[v]}{degree[u]}[E(u,v)=0] + \sum \frac{(1-f[v])}{degree[u]}[E(u,v)=1]\]
然后你会发现这样转移不了,因为对应的\(f[v]\)可能还未确定。
所以\(f[x]\)之间是互相影响的,没有办法直接转移。 怎么办呢?
B
本题最超神的地方来了。
我们观察每一个方程:
\[f[u] = \sum \frac{f[v]}{degree[u]}[E(u,v)=0] + \sum \frac{(1-f[v])}{degree[u]}[E(u,v)=1]\]
移项:
\[f[u]+\sum \frac{f[v]}{degree[u]}[E(u,v)=1] - \sum \frac{f[v]}{degree[u]}[E(u,v)=0] = \sum [E(u,v)=1]\]
把每一个\(f[i]\)看做一个未知数\(x_i\),那么刚好有\(n\)个方程。
高斯消元即可(太神奇了原来高斯消元还可以这么用).......
实现代码:
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define _ 105
using namespace std;
struct Road{int to,next,val;}t[2*_*_];
double ans , f[_][_] , deg[_]; int head[_],d[_],n,m,cnt;
IL void Build(RG int jd){
memset(f,0,sizeof(f));
for(RG int u = 1; u < n; u ++){ //注意n的方程要特判!!
f[u][u] = 1.0;
for(RG int e = head[u]; e ; e = t[e].next){
RG int v = t[e].to , w = ((t[e].val>>jd)&1);
if(w!=0)f[u][n+1] += 1.0/deg[u] , f[u][v] += 1.0/deg[u];
else f[u][v] -= 1.0/deg[u];
}
}f[n][n] = 1.0; return;
}
IL void Gauss(){
for(RG int j = 1; j <= n; j ++){
RG int rgt = 0;
for(RG int i = j; i <= n; i ++)
if(f[i][j]){rgt = i; break;}
if(!rgt)continue;
if(rgt ^ j)swap(f[rgt],f[j]);
for(RG int i = j+1; i <= n; i ++){
RG double div = f[i][j] / f[j][j];
for(RG int k = 1; k <= n+1; k ++)
f[i][k] -= 1.0 * f[j][k] * div;
}
}
for(RG int j = n; j >= 1; j --){
f[j][n+1] = f[j][n+1] / f[j][j];
for(RG int i = j-1; i >= 1; i --)
f[i][n+1] -= 1.0*f[i][j] * f[j][n+1];
}return;
}
int main(){
cin >> n >> m;
for(RG int i = 1; i <= m; i ++){
RG int u,v,w;
cin >> u >> v >> w;
t[++cnt] = (Road){v,head[u],w} , head[u] = cnt , d[u]++;
if(u^v)t[++cnt] = (Road){u,head[v],w} , head[v] = cnt , d[v]++;
//特别注意如果这里是自环只能连一条边。
}
for(RG int i = 1; i <= n; i ++)deg[i] = d[i];
ans = 0;
for(RG int e = 0; e <= 30; e ++){
Build(e); Gauss();
double nm = 1.0*(1<<e);
ans = ans + 1.0*nm*f[1][n+1];
}
printf("%.3lf",ans); return 0;
}
补充题:[HNOI2013]游走
然而,你以为这样就完了吗.......
这里还有一道更加恶心的:[HNOI2013]游走
壮哉我大湖南,尽出这种毒瘤题........
题目大意:
一个无向连通图,顶点从\(1\)编号到\(N\),边从\(1\)编号到\(M\)。
小Z在该图上进行随机游走,初始时小Z在\(1\)号顶点,
每一步小Z以相等的概率随机选择当前顶点的某条边,
沿着这条边走到下一个顶点,获得等于这条边的编号的分数。
当小Z到达\(N\)号顶点时游走结束,总分为所有获得的分数之和。
现在,请你对这\(M\)条边进行编号,使得小Z获得的总分的期望值最小。
数据范围:\(N\leq 500\) , \(M\leq 100000\)
题目解法:
这题作为补充就不写的那么详细了,那个贪心直接跳过。
关键的一步:把求边的概率转换到求点的概率。
假设一个点\(x\)在\(1\)到\(n\)的路径上被经过的概率为\(p_x\) , 那么
\[p_{<u,v>} = \frac{p_{u}}{degree[u]} + \frac{p_{v}}{degree[v]} \]
然后就只要求\(p_u\)了。 显然有方程式: \(p_u = \sum \frac{p_v}{degree[v]}\)
移一下项得到:\(p_u - \sum \frac{p_v}{degree[v]} = 0\) ;与上题类似高斯消元即可。
然后注意一下子边界问题,我在代码里面详细讲了。
实现代码:
注:这题 \(Luogu\) 数据真的太卡精度了,这份代码交上去只能获得 70分。
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define _ 505
#define eps 1e-7
using namespace std;
double fc[_][_] , deg[_] , ans[_]; int n,m;
struct Edge{
int x1,x2; double p;
bool operator < (const Edge &B)const{
return p > B.p;}
}eg[2*_*_];
struct Road{int to,next;}t[_*_*2]; int head[_],cnt;
IL void Gauss(){
for(RG int j = 1; j < n; j ++){
RG int r = 0;
for(RG int i = j; i < n; i ++)
if(fc[i][j]){r = i; break;}
if(r <= eps)continue;
if(r ^ j)swap(fc[r] , fc[j]);
for(RG int i = j+1; i < n; i ++){
RG double div = (fc[i][j] / fc[j][j]);
for(RG int k = 1; k <= n; k ++)
fc[i][k] -= div*fc[j][k];
}
}
for(RG int j = n-1; j >= 1; j --){
ans[j] = fc[j][n] / fc[j][j];
for(RG int i = j-1; i >= 1; i --)
fc[i][n] -= ans[j] * fc[i][j];
}return;
}
int main(){
cin >> n >> m;
for(RG int i = 1; i <= n; i ++)
fc[i][i] = 1.0;
for(RG int sq = 1; sq <= m; sq ++){
RG int u , v;
cin >> u >> v;
eg[sq] = (Edge){u,v,0};
deg[u] += 1.0 ; if(u^v)deg[v] += 1.0;
t[++cnt] = (Road){v,head[u]}; head[u] = cnt;
if(u ^ v)t[++cnt] = (Road){u,head[v]}; head[v] = cnt;
}
for(RG int u = 1; u < n; u ++){
for(RG int i = head[u]; i; i = t[i].next){
RG int v = t[i].to;
if(v ^ n)fc[u][v] -= 1.0/deg[v];
}
}
fc[1][n] = 1.0;
//注:由于到了n之后游走就结束了,所以为了不影响其它方程的求解,f[n] = 0;
//为了省空间,把原来的常数项(答案项)向左移了一个移到了fc[i][n];
//由于1、n是一定会经过的,所以它们的答案为1.0,即fc[1][n] = fc[n][n] = 1.0;
Gauss();
for(RG int i = 1,u,v; i <= m; i ++)
u = eg[i].x1,v = eg[i].x2 ,
eg[i].p = ans[u]/deg[u] + ans[v]/deg[v];
sort(eg+1,eg+m+1);
RG double res =0,oo;
for(RG int i = 1; i <= m; i ++)
oo = i , res = res + 1.0*oo*eg[i].p; //p从大到小排序。
printf("%.3lf",res); return 0;
}
[HNOI2011]XOR和路径 && [HNOI2013]游走的更多相关文章
- [HNOI2011]XOR与路径
https://zybuluo.com/mdeditor#1094266 标签(空格分隔): 高斯消元 期望 题面 从 1 号节点开始,以相等的概率,随机选择与当前节点相关联的某条边,并沿这条边走到下 ...
- BZOJ2337: [HNOI2011]XOR和路径
题解: 异或操作是每一位独立的,所以我们可以考虑每一位分开做. 假设当前正在处理第k位 那令f[i]表示从i到n 为1的概率.因为不是有向无环图(绿豆蛙的归宿),所以我们要用到高斯消元. 若有边i-& ...
- BZOJ 2337: [HNOI2011]XOR和路径 [高斯消元 概率DP]
2337: [HNOI2011]XOR和路径 题意:一个边权无向连通图,每次等概率走向相连的点,求1到n的边权期望异或和 这道题和之前做过的高斯消元解方程组DP的题目不一样的是要求期望异或和,期望之间 ...
- [HNOI2011]XOR和路径
题面在这里 题意:给定一个无向图,从1号节点出发,每次等概率选择连接该节点的一条边走到另一个节点,到达n号节点时,将走过的路径上的所有边权异或起来,求这个异或和的期望 sol 一道期望大火题(表示看了 ...
- 【BZOJ 2337】 2337: [HNOI2011]XOR和路径(概率DP、高斯消元)
2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1170 Solved: 683 Description ...
- 【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径
2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 682 Solved: 384[Submit][Stat ...
- bzoj 3143: [Hnoi2013]游走 高斯消元
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1026 Solved: 448[Submit][Status] ...
- BZOJ 2337: [HNOI2011]XOR和路径( 高斯消元 )
一位一位考虑异或结果, f(x)表示x->n异或值为1的概率, 列出式子然后高斯消元就行了 --------------------------------------------------- ...
- [补档][Hnoi2013]游走
[Hnoi2013]游走 题目 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一 ...
随机推荐
- Es6 Symbol.iterator
Symbol.iterator 为每一个对象定义了默认的迭代器.该迭代器可以被 for...of 循环结构使用. --描述 当需要迭代一个对象的时候(比如在 for...of 循环的开始时),它的 @ ...
- 小笔记:Timer定时间隔时间操作
小笔记:Timer定时间隔时间操作,后面有时间再补充和完善: public class TimingSvc { /// <summary> /// 定时器,执行定时任务 /// </ ...
- linear-grident的属性和使用以及对颜色后面参数(百分比)的理解
linear-grident的属性和使用 css3新增Gradient属性,用来增加渐变的效果,渐变分为线性渐变 linear-grident 和 径向渐变 radial-grident,这篇文章 ...
- VSCode插件MSSQL教程(昨天提了一下)
推荐一个跨平台SQL IDE:https://docs.microsoft.com/zh-cn/sql/sql-operations-studio/download 什么数据库都木有(系统自带的不算) ...
- 试用MarkDown
自定义界面风格 可以在设置中选择日间,或者夜间模式进行定义.具体的定义项的说明,可以查看菜单栏 (Windows版本位于托盘按钮上) 自定义的帮助. MarkEditor几乎所有跟色彩有关的界面,都已 ...
- ASP.NET CORE MVC 实现减号分隔(Kebab case)样式的 URL
ASP.NET CORE MVC 中,默认的 Route 模板是: /{controller}/{action} .我们可以通过开启 URL 小写转换将 URL 变为小写,但此方式在 Control ...
- Mysql的sql_mode
(一) 基本介绍 set sql_mode="",即强制不设定MySql模式(如不作输入检测.错误提示.语法模式检查等)应该能提高性能,但有如下问题: 如果插入了不合适数据(错误类 ...
- Angular Universal(统一平台)笔记
angular官网高级文档AngularUniversal部分的翻译总结,这东西在angular4开始正式被官方支持了,目前其实支持的服务器端还没有很多,但好歹包括了node和DotNetCore,算 ...
- 四级地址插件升级改造(京东商城地址选择插件)city-picker
最近公司做的项目要和京东的数据做对接,所以要做个类似京东商品的详情页.页面的数据,是可以从京东接口获取到的,但是地址插件选择的效果需要自己实现.前端的同事在之前的项目中,已经选择了一款地址插件(cit ...
- Extjs 4.0 Tab页
1.JSON代码 Ext.MyTabs=Ext.extend(Ext.TabPanel ,{ xtype:"tabpanel", activeTab:2, width:694, h ...