AtCoder Beginner Contest 336 G. 16 Integers(图计数 欧拉路径转欧拉回路 矩阵树定理 best定理)

news2024/9/24 22:43:44

题目

给16个非负整数,x[i∈(0,1)][j∈(0,1)][k∈(0,1)][l∈(0,1)]

求长为n+3的01串的方案数,满足长度为4的ijkl(2*2*2*2,16种情况)串恰为x[i][j][k][l]个

答案对998244353取模

思路来源

https://www.cnblogs.com/tzcwk/p/matrix-tree-best-theroem.html

矩阵树定理 - OI Wiki

知识点总结

矩阵树定理

对于一张无向图G,

记D为其度数矩阵,满足:

1. D[i][i]=i的度数

2. D[i][j]=0(i≠j)

记A为其邻接矩阵,满足:

1. A[i][j]=i与j之间边的条数,如果有重边则算作多条边。

记基尔霍夫矩阵(拉普拉斯矩阵)K=D−A,

则去掉第k行第k列得到的矩阵行列式即为G生成树的个数。

BEST 定理

对于一个欧拉图(有向图)而言,

从x出发回到x的欧拉回路的个数为:

t^{root}(n,k)*\prod_{v\epsilon V}(deg(v)-1)!

其中,t^{root}(n,k)为任一个点的根向树形图的数量,用矩阵树定理求得,

后半部分,即对于每个点,再乘以每个点的度数减1的阶乘

根向树形图

根向树形图是一棵树,所有边都往根的方向指

一些技巧

求欧拉路径的数量

二层枚举欧拉路径的起点、终点,钦定加一条终点到起点的边,转化为求欧拉回路

仅要求所有边经过一次(部分点可以孤立)

忽略掉孤立点后,对剩下的点离散化后,重新建矩阵,求矩阵的秩

需要视题目决定是否需要乘deg[v](从v出发回到v)

少乘度数的是带循环同构的边序列

思路来源

官方题解

题解

1. 把形如abcd的出现次数,转化为abc->bcd有向边的边的条数,

转化为成边数后,即求欧拉路径条数,

枚举欧拉路径起点终点后,强制加一条边,转成欧拉回路后,套用best定理

2. 对于枚举起点为i,终点为j的情况,先强制加一条j->i的边,

统计每个点x的入度in[x]、出度out[x]

① 忽略孤立点,即in[x]=out[x]=0

② 若in[x]和out[x]不相等,则无解

③ 若x非孤立点,且与i不联通,则无解

否则,

④忽略孤立点,将非孤立点重新编号建边

⑤按定义构建基尔霍夫矩阵K=D-A

即a[k][k]+=in[k](D矩阵),a[k][l]-=b[k][l](A矩阵)

            rep(k,0,7){ // 基尔霍夫矩阵
                a[to[k]][to[k]]=in[k];
                rep(l,0,7){
                    if(!to[l])continue;
                    a[to[k]][to[l]]-=b[k][l];
                    //printf("%d ",a[k][l]);
                }
            }

⑥求矩阵的秩,得到生成树数量,依次乘以(deg[i]-1)!得到欧拉回路数量

⑦欧拉回路是一个环,每个环被统计一次,

固定新增的那条边在串最后指向串最前,即可唯一对应一个串

但是注意到,当abc->bcd有两条相同的边x1、x2时,二者的顺序会被欧拉回路视为不同的方案

而在序列中,abcd是一个唯一的序列,被重复计算

所以,需要除掉完全相同的边的顺序,类似可重集全排列的方案数

代码

// Problem: G - 16 Integers
// Contest: AtCoder - AtCoder Beginner Contest 336
// URL: https://atcoder.jp/contests/abc336/tasks/abc336_g
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=1e6+10,M=16,K=8,mod=998244353;
int t,fac[N],x[M],b[K][K],in[K],out[K],par[K];
int find(int x){
	return par[x]==x?x:par[x]=find(par[x]);
}
void merge(int x,int y){
	x=find(x),y=find(y);
	if(x==y)return;
	par[y]=x;
}
int modpow(int x,int n,int mod){
	int res=1;
	for(;n;n>>=1,x=1ll*x*x%mod){
		if(n&1)res=1ll*res*x%mod;
	}
	return res;
}
// 求解行列式时模数不是质数,没法求逆元,这时只能利用辗转消除法进行高斯消元
// 矩阵的秩
int Gauss(vector<vector<int> >&a,int n){
	//printf("x:%d\n",x);
    int ans=1;
    //swap(a[0],a[x]);
    for(int i=2;i<=n;i++){
        for(int j=i;j<=n;j++){
            if(!a[i][i] && a[j][i]){
                swap(a[i],a[j]);
                ans=mod-ans;
                break;
            }
        }
        ans=1ll*ans*a[i][i]%mod;
        for(int j=1;j<=n;j++){
            if(i==j || !a[j][i])continue;
            int t=1ll*a[j][i]*modpow(a[i][i],mod-2,mod)%mod;
            for(int k=1;k<=n;k++){
                a[j][k]=(a[j][k]-1ll*t*a[i][k]%mod+mod)%mod;
            }
        }
    }
    return ans;
}
void sol(){
	rep(i,0,15){
		b[i>>1][i&7]=x[i];
	}
	int res=0;
	rep(i,0,7){
		rep(j,0,7){
			b[j][i]++;//欧拉路径->欧拉回路
			bool ok=1;
			memset(in,0,sizeof in);
			memset(out,0,sizeof out);
			rep(k,0,7)par[k]=k;
			rep(k,0,7){
				rep(l,0,7){
					in[l]+=b[k][l];
					out[k]+=b[k][l];
					if(b[k][l])merge(k,l);
					//if(b[k][l])printf("i:%d j:%d k:%d l:%d b:%d\n",i,j,k,l,b[k][l]);
				}
			}
			rep(k,0,7){
				if(!in[k] && !out[k])continue;//孤立点,只是要求遍历所有边时,可忽略
				if(in[k]!=out[k])ok=0;//判出入度
				if(find(k)!=find(i))ok=0;//判连通
				//printf("i:%d j:%d k:%d in:%d out:%d\n",i,j,k,in[k],out[k]);
			}
			if(!ok){
				b[j][i]--;
				continue;
			}
			int bs=1;//deg[i]
			rep(k,0,7){
				if(!in[k])continue;
				bs=1ll*bs*fac[in[k]-1]%mod;//\prod (deg[i]-1)
			}
			vector<vector<int>>a(K+1,vector<int>(K+1,0));
			vector<int>to(K+1,0);
			int id=0;
			rep(k,0,7){
				if(in[k])to[k]=++id;
			}
			rep(k,0,7){ // 基尔霍夫矩阵
				a[to[k]][to[k]]=in[k];
				rep(l,0,7){
					if(!to[l])continue;
					a[to[k]][to[l]]-=b[k][l];
					//printf("%d ",a[k][l]);
				}
			}
			int rank=Gauss(a,id);//求基尔霍夫矩阵的秩
			//printf("i:%d j:%d bs:%d rk:%d\n",i,j,bs,rank);
			bs=1ll*bs*rank%mod;
			rep(k,0,15){
				bs=1ll*bs*modpow(fac[x[k]],mod-2,mod)%mod;//去重
			}
			res=(res+bs)%mod;
			b[j][i]--;
		}
	}
	printf("%d\n",res);
}
void init(){
	fac[0]=1;
	rep(i,1,N-1)fac[i]=1ll*fac[i-1]*i%mod;
}
int main(){
	init();
	rep(i,0,15)sci(x[i]);
	sol();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1387889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多线程并发与并行

&#x1f4d1;前言 本文主要是【并发与并行】——并发与并行的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&…

03 顺序表

目录 线性表顺序表练习 线性表(Linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串。。。 线性表在逻辑上时线性结构&#xff0c;是连续的一条直线。但在物理结…

【PostgreSQL内核学习(二十一)—— 执行器(InitPlan)】

执行器&#xff08;InitPlan&#xff09; 概述InitPlan 函数代码段解释ExecInitNode 函数 总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明…

力扣每日一练(24-1-16)

我一开始想到的是&#xff0c;如果数字相同则加一。 然而&#xff0c;对了一点点&#xff0c;而已。 高手的方法不是普通人在几分钟内能想得出来的&#xff0c;hh 继续补充&#xff1a; 如果数字不同则减一&#xff0c;如果计数到达了0&#xff0c;则更新数字&#xff0c;最…

【极光系列】springboot集成redis

【极光系列】springboot集成redis tips&#xff1a;主要用于快速搭建环境以及部署项目入门 gitee地址 直接下载源码可用 https://gitee.com/shawsongyue/aurora.git模块&#xff1a;aurora_rediswindow安装redis安装步骤 1.下载资源包 直接下载解压&#xff1a;https://pa…

PHP项目如何自动化测试

开发和测试 测试和开发具有同等重要的作用 从一开始&#xff0c;测试和开发就是相向而行的。测试是开发团队的一支独立的、重要的支柱力量。 测试要具备独立性 独立分析业务需求&#xff0c;独立配置测试环境&#xff0c;独立编写测试脚本&#xff0c;独立开发测试工具。没有…

华硕原厂系统天选5Pro原厂Win11系统恢复安装过程方法

华硕原厂系统天选5Pro原厂Win11系统恢复安装过程方法 华硕原厂系统枪神8/枪神8plus原厂Win11系统恢复安装过程方法 还是老规矩&#xff0c;分3种安装方法 远程恢复安装&#xff1a;https://pan.baidu.com/s/166gtt2okmMmuPUL1Fo3Gpg?pwdm64f 提取码:m64f 支持型号&#x…

new Handler(getMainLooper())与new Handler()的区别

Handler 在Android中是一种消息处理机制。 new Handler(); 创建handler对象&#xff0c;常用在已经初始化了 Looper 的线程中调用这个构造函数&#xff08;即非主线程&#xff09;&#xff0c;如果感觉不好理解&#xff0c;可以把Handler handler new Handler() 理解为常用在…

Vue3中使用自定义指令

一&#xff0c;自定义指令&#xff1a; 应用场景&#xff1a;禁用按钮多次点击 1.vue2 a. src/libs/preventClick.js import Vue from vue const preventClick Vue.directive(preventClick, {inserted: function (el, binding) {el.addEventListener(click, () > {if (!el…

MySQL多表查询(改进版)

1.创建student和score表 mysql> CREATE TABLE student (-> id INT(10) NOT NULL UNIQUE PRIMARY KEY ,-> name VARCHAR(20) NOT NULL ,-> sex VARCHAR(4) ,-> birth YEAR,-> department VARCHAR(20) ,-> address VARCHAR(50)-> ); Query O…

C#用double.TryParse(String, Double)方法将字符串类型数字转换为数值类型

目录 一、定义 二、实例 命名空间: System 程序集: System.Runtime.dll 一、定义 将数字的字符串表示形式转换为它的等效双精度浮点数。 一个指示转换是否成功的返回值。 public static bool TryParse (string? s, out double result…

Rust-所有权和移动语义

什么是所有权 拿C语言的代码来打个比方。我们可能会在堆上创建一个对象&#xff0c;然后使用一个指针来管理这个对象&#xff1a; Foo *p make_object("args");接下来&#xff0c;我们可能需要使用这个对象&#xff1a; use_object(p);然而&#xff0c;这段代码之…

初识OpenCV

首先你得保证你的虚拟机Ubuntu能上网 可看 http://t.csdnimg.cn/bZs6c 打开终端输入 sudo apt-get install libopencv-dev 回车 输入密码 回车 遇到Y/N 回车 OpenCV在线文档 opencv 文档链接 点zip可以下载&#xff0c;点前面的直接在线浏览&#xff0c;但是很慢 https…

AI嵌入式K210项目(3)-GPIO控制

文章目录 前言一、背景知识二、背景知识二、开始你的表演代码实现 总结 前言 前面介绍了开发板和环境搭建的基本情况&#xff0c;接下来我们开始学习使用C进行裸板开发&#xff0c;本节课先来学习下K210最基础的功能&#xff0c;引脚映射和点灯。 在开始具体学习之前&#xff…

跟着cherno手搓游戏引擎【4】窗口抽象、GLFW配置、窗口事件

引入GLFW&#xff1a; 在vendor里创建GLFW文件夹&#xff1a; 在github上下载&#xff0c;把包下载到GLFW包下。 GitHub - TheCherno/glfw: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input修改SRC/premake5.lua的配置&#xff1a;12、13、15、36…

多云架构下的点击流数据分析

在出海的大趋势下&#xff0c;需要对点击流数据进行分析&#xff0c;以便更快的确定客户。作为多家云厂商的合作伙伴&#xff0c;九河云将提供点击流数据分析的改良方案。 对于这个需求可以借助aws的受众细分和定位解决方案&#xff0c;您可以应用基于云的分析和机器学习来减少…

Seaborn——可视化的具体API应用

一、Seaborn概述 Seaborn 是基于 matplotlib的图形可视化 python包。提供了一种高度交互式界面&#xff0c;便于用户能够做出各种有吸引力的统计图表。 Seaborn在 matplotlib的基础上进行了更高级的API封装&#xff0c;从而使得作图更加容易&#xff0c;在大多数情况下使用seab…

高可用架构去中心化重要?

1 背景 在互联网高可用架构设计中&#xff0c;应该避免将所有的控制权都集中到一个中心服务&#xff0c;即便这个中心服务是多副本模式。 对某个中心服务&#xff08;组件&#xff09;的过渡强依赖&#xff0c;那等同于把命脉掌握在依赖方手里&#xff0c;依赖方的任何问题都可…

kafka学习笔记-- 文件清理策略与高效读写数据

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…

机器学习学习笔记(吴恩达)(第三课第一周)(无监督算法,K-means、异常检测)

欢迎 聚类算法&#xff1a; 无监督学习&#xff1a;聚类、异常检测 推荐算法&#xff1a; 强化学习&#xff1a; 聚类&#xff08;Clustering&#xff09; 聚类算法&#xff1a;查看大量数据点并自动找到彼此相关或相似的数据点。是一种无监督学习算法 聚类与二院监督…