自己 yy 了一个动态 dp 做法,应该是全网唯一用 LCT 写的.

code:

#include <bits/stdc++.h>
#define ll long long
#define lson tr[x].ch[0]
#define rson tr[x].ch[1]
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
const int N=200005;
const ll mod=998244353;
vector<int>EDGE;
int edges=1,n,m,F[N][2];
int hd[N],to[N<<1],nex[N<<1],from[N<<1],mark[N<<1],vis[N],sta[N];
int qpow(int x,int y)
{
int tmp=1;
while(y)
{
if(y&1) tmp=1ll*tmp*x%mod;
x=1ll*x*x%mod, y>>=1;
}
return tmp;
}
int INV(int x) { return qpow(x,mod-2); }
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,from[edges]=u;
}
void dfs(int u,int ff)
{
vis[u]=1;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||mark[i]) continue;
if(vis[v])
{
mark[i]=mark[i^1]=1, EDGE.push_back(i);
continue;
}
dfs(v,u);
}
}
struct Num
{
int val,cnt;
Num() { val=cnt=0; }
void ins(int a)
{
val=a,cnt=0;
if(!val) val=1,cnt=1;
}
Num operator*(Num b) const
{
Num re;
re.val=1ll*val*b.val%mod;
re.cnt=cnt+b.cnt;
return re;
}
Num operator/(Num b) const
{
Num re;
re.cnt=cnt-b.cnt;
re.val=1ll*val*INV(b.val)%mod;
return re;
}
int get() { return cnt?0:val; }
}tmp[N][2][2];
struct matrix
{
int a[2][2];
matrix() { memset(a,0,sizeof(a)); }
void I()
{
a[0][0]=a[1][1]=1;
a[0][1]=a[1][0]=0;
}
int *operator[](int x) { return a[x]; }
}t[N],po[N];
matrix operator*(matrix a,matrix b)
{
matrix c;
for(int i=0;i<2;++i)
{
for(int j=0;j<2;++j)
for(int k=0;k<2;++k)
c[i][j]=(c[i][j]+1ll*a[i][k]*b[k][j]%mod)%mod;
}
return c;
}
void cop(int x)
{
for(int i=0;i<2;++i)
{
for(int j=0;j<2;++j)
t[x][i][j]=tmp[x][i][j].get();
}
}
struct node
{
int ch[2],f,rev;
}tr[N];
int get(int x)
{
return tr[tr[x].f].ch[1]==x;
}
int isrt(int x)
{
return !(tr[tr[x].f].ch[0]==x||tr[tr[x].f].ch[1]==x);
}
void pushup(int x)
{
cop(x);
t[x]=po[x]*t[x];
if(lson) t[x]=t[lson]*t[x];
if(rson) t[x]=t[x]*t[rson];
}
void rotate(int x)
{
int old=tr[x].f,fold=tr[old].f,which=get(x);
if(!isrt(old)) tr[fold].ch[tr[fold].ch[1]==old]=x;
tr[old].ch[which]=tr[x].ch[which^1],tr[tr[old].ch[which]].f=old;
tr[x].ch[which^1]=old,tr[old].f=x,tr[x].f=fold;
pushup(old),pushup(x);
}
void splay(int x)
{
int u=x,v=0,fa;
for(sta[++v]=u;!isrt(u);u=tr[u].f) sta[++v]=tr[u].f;
for(u=tr[u].f;(fa=tr[x].f)!=u;rotate(x))
{
if(tr[fa].f!=u)
{
rotate(get(fa)==get(x)?fa:x);
}
}
}
void Access(int x)
{
for(int y=0;x;y=x,x=tr[x].f)
{
splay(x);
if(rson)
{
Num a,b;
a.ins(t[rson][0][0]);
b.ins(t[rson][0][0]+t[rson][1][0]);
tmp[x][1][0]=tmp[x][1][0]*a;
tmp[x][0][0]=tmp[x][0][0]*b;
tmp[x][0][1]=tmp[x][0][1]*b;
}
if(y)
{
Num a,b;
a.ins(t[y][0][0]);
b.ins(t[y][0][0]+t[y][1][0]);
tmp[x][1][0]=tmp[x][1][0]/a;
tmp[x][0][0]=tmp[x][0][0]/b;
tmp[x][0][1]=tmp[x][0][1]/b;
}
rson=y;
pushup(x);
}
}
void prepare(int u,int ff)
{
po[u].I();
tr[u].f=ff;
tmp[u][1][1].ins(0);
tmp[u][0][0].ins(1);
tmp[u][0][1].ins(1);
tmp[u][1][0].ins(1);
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||mark[i]) continue;
prepare(v,u);
Num a,b;
a.ins(tmp[v][0][0].get());
b.ins(tmp[v][0][0].get()+tmp[v][1][0].get());
tmp[u][0][0]=tmp[u][0][0]*b;
tmp[u][0][1]=tmp[u][0][1]*b;
tmp[u][1][0]=tmp[u][1][0]*a;
}
pushup(u);
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs(1,0);
prepare(1,0);
ll ans=0ll;
int sta=EDGE.size();
if(sta==0)
{
Access(3),splay(3);
ans=(t[3][0][0]+t[3][1][0])%mod;
}
else
{
for(i=0;i<(1<<sta);++i)
{
for(j=0;j<sta;++j)
{
if(i&(1<<j))
{
int u=from[EDGE[j]];
int v=to[EDGE[j]];
Access(u),splay(u);
po[u][0][0]=0;
pushup(u); Access(v),splay(v);
po[v][1][1]=0;
pushup(v);
}
else
{
int u=from[EDGE[j]];
Access(u),splay(u);
po[u][1][1]=0;
pushup(u);
}
}
Access(1),splay(1);
(ans+=(t[1][0][0]+t[1][1][0])%mod)%=mod;
for(j=0;j<sta;++j)
{
if(i&(1<<j))
{
int u=from[EDGE[j]];
int v=to[EDGE[j]];
Access(u),splay(u);
po[u][0][0]=1;
pushup(u);
Access(v),splay(v);
po[v][1][1]=1;
pushup(v);
}
else
{
int u=from[EDGE[j]];
Access(u),splay(u);
po[u][1][1]=1;
pushup(u);
}
}
}
}
printf("%lld\n",ans);
return 0;
}

  

BZOJ 5287: [Hnoi2018]毒瘤 动态dp(LCT+矩阵乘法)的更多相关文章

  1. BZOJ 4712 洪水 动态dp(LCT+矩阵乘法)

    把之前写的版本改了一下,这个版本的更好理解一些. 特地在一个链的最底端特判了一下. code: #include <bits/stdc++.h> #define N 200005 #def ...

  2. bzoj 5287: [Hnoi2018]毒瘤

    Description Solution \(dfs\) 出一棵生成树之后,多出来的边就都是反祖边了 把反祖边两个端点都拿出来,就会得到最多 \(k=2*(m-n+1)\) 个关键点 除了关键点以外的 ...

  3. 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法

    题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...

  4. bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1009 [题意] 给定一个字符串T,问长度为n且不包含串T的字符串有多少种. [思路] ...

  5. BZOJ 1444 [JSOI2009]有趣的游戏 (AC自动机、概率与期望DP、矩阵乘法)

    诶这题洛谷居然没有??? 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1444 题解: 我见到主要有三种做法. 一是矩阵乘法.设\(d ...

  6. 【BZOJ2510】弱题 期望DP+循环矩阵乘法

    [BZOJ2510]弱题 Description 有M个球,一开始每个球均有一个初始标号,标号范围为1-N且为整数,标号为i的球有ai个,并保证Σai = M. 每次操作等概率取出一个球(即取出每个球 ...

  7. [HNOI2008]GT考试(kmp,dp,矩阵乘法)

    [HNOI2008]GT考试(luogu) Description 求有多少个n位的数字串不包含m位的字符串(范围 n <= 1e9 n<=1e9, m <= 20m<=20) ...

  8. BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法

    标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...

  9. BZOJ 1875: [SDOI2009]HH去散步(矩阵乘法)

    首先,题意就把我们引向了矩阵乘法,注意边长m<=60,那么就按边建图,变成一个120个点的图,然后乱搞就行了。 PS:WA了N久改了3次终于A了QAQ CODE: #include<cst ...

随机推荐

  1. mysql5.7新增加用户和授权

    迁移mysql数据库,运行项目的时候发现nginx和uWSGI都配置正确,可就是网站打不开,看了log文件,发现错误: django.db.utils.OperationalError: (1044, ...

  2. webpack 打包出多个HTML文件,多个js文件,图片文件放置到指定文件夹中

    一.webpack.config.js简单代码 const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { ...

  3. java之hibernate之 cascade和inverse

    1.Cascade是级联动作,在many_to_one中如果使用cascade可以级联操作关联对象,如下代码可以级联保存Category对象. 在Book的映射文件设置 <many-to-one ...

  4. asp.net core 之中间件

    Http请求资源的过程可以看成一个管道:“Pipe”,并不是所有的请求都是合法的.安全的,其于功能.性能或安全方面的考虑,通常需要在这管道中装配一些处理程序来筛选和加工这些请求.这些处理程序就是中间件 ...

  5. 表单提交学习笔记(二)—使用jquery.validate.js进行表单验证

    一.官网下载地址:http://plugins.jquery.com/validate/ 二.用法 1.在页面上进行引用 <script src="~/scripts/jquery-1 ...

  6. NMS(non maximum suppression,非极大值抑制)

    """nms输入的数据为box的左上角x1,y1与右下角x2,y2+confidence,rows=batch_size,line=[x1,y1,x2,y2,confid ...

  7. LRU(Least Recently Used)算法的理解

    https://blog.csdn.net/wydyd110/article/details/84023688 感谢 ,自己学习记笔记 内存里建立一个哈希表,后来数据多了,爆了.咋整呢? 一个算法,就 ...

  8. 解决vue-cli项目开发中跨域问题

    一.开发环境中跨域 使用 Vue-cli 创建的项目,开发地址是 localhost:8080,需要访问非本机上的接口http://10.1.0.34:8000/queryRole.不同域名之间的访问 ...

  9. pip笔记(译)

    从PyPI中安装包 >>> pip install SomePackage [...] Successfully installed SomePackage 从PyPI或其他地方安装 ...

  10. Mysql5.7 建表报 [Err] 1055 问题

    最近,在win10系统上,使用docker下载了 mysql5.7镜像,然后建表时,发生奇怪的问题,表正常创建,但底部会出现一行错误信息,如下: [Err] 1055 - Expression #1 ...