【HNOI2009】bzoj1488 图的同构

2023-11-07 19:48
文章标签 hnoi2009 同构 bzoj1488

本文主要是介绍【HNOI2009】bzoj1488 图的同构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先可以把问题转化成在完全图上对边进行黑白染色。
对于每个点的置换,要求出有多少关于边的不动点。把置换分解成循环,可以发现,一个长度为 x 的点的循环内部有x2个边的循环,两个长度为 x y的点的循环之间有 gcd(x,y) 个边的循环,这样关于边的不动点总数就是 2m ,其中 m 表示边的循环的总数。
但是直接枚举点的置换有n!种,显然无法承受。因为每种置换对答案的贡献只和每个循环的大小有关,可以枚举 n 的正整数拆分,然后对每种拆分计算对应的置换个数。具体来说,记有m个循环,每个循环的长度为 li ,每个长度的循环有 ci 个。首先给每个循环分配一个位置

(nl1)(nl1l2)(nl1lm1lm)=n!li!

然后,固定第一个元素,每个循环有 (li1)! 种排法。同时,相同长度的循环彼此之间的顺序被重复考虑。所以最后的答案是
n!lici

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int p=997;
int n,ans,fac[65],inv[65],invfac[65],cnt[65],a[65],gcd[65][65],node;
int pow(int base,int k)
{int ret=1;for (;k;k>>=1,base=base*base%p)if (k&1) ret=ret*base%p;return ret;
}
int getgcd(int x,int y)
{if (gcd[x][y]) return gcd[x][y];return gcd[x][y]=y?getgcd(y,x%y):x;
}
void check()
{int ret=fac[n],tot=0,sum=0;for (int i=1;i<=n;i++){ret=ret*invfac[cnt[i]]%p;for (int j=1;j<=cnt[i];j++)a[++tot]=i,ret=ret*inv[i]%p;}for (int i=1;i<=tot;i++){sum+=a[i]/2;for (int j=i+1;j<=tot;j++) sum+=gcd[a[i]][a[j]];}ret=ret*pow(2,sum)%p;ans=(ans+ret)%p;
}
void dfs(int now,int num)
{//node++;if (now==1){cnt[1]=n-num;check();return;}for (int i=0;num+i*now<=n;i++){cnt[now]=i;dfs(now-1,num+i*now);}
}
int main()
{scanf("%d",&n);fac[0]=invfac[0]=1;for (int i=1;i<=n;i++){fac[i]=fac[i-1]*i%p;inv[i]=pow(i,p-2);invfac[i]=pow(fac[i],p-2);}for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)gcd[i][j]=getgcd(i,j);dfs(n,0);//printf("%d\n",node);printf("%d\n",ans*invfac[n]%p);
}

这篇关于【HNOI2009】bzoj1488 图的同构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/365893

相关文章

浙大数据结构——03-树1 树的同构

这道题我依然采用STL库的map,从而大幅减少了代码量 简单说一下思路,两棵树是否同构,只需比较俩树字母相同的结点是否同构,即是否左==左,右==右或者左==右,右==左。 1、条件准备 atree和btree是存两个数结点字母,第几个就存输入的第几个结点的字母。 map通过结点的字母作为键,从而找到两个子节点的信息 都要用char类型 #include <iostream>#inc

LeetCode题练习与总结:同构字符串--205

一、题目描述 给定两个字符串 s 和 t ,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。 示例 1: 输入:s = "egg", t = "add"输出:true 示例 2

SSR 学习 - 传统服务端渲染 Web 应用、客户端渲染、同构渲染、优缺点和案例演示

概述 随着前端技术栈和工具链的迭代成熟,前端工程化、模块化也已成为了当下的主流技术方案。 在这波前端技术浪潮中,涌现了诸如 React、Vue、Angular 等基于客户端渲染的前端框架。 这类框架所构建的 **单页应用(SPA)**的优点: 用户体验好开发效率高渲染性能好可维护性好… **单页应用(SPA)**也有一些很大的缺陷,其中主要涉及到以下两点: 首屏渲染时间过长 与传统服务

[字符串]205. 同构字符串

给定两个字符串 s 和 t,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。 示例 1: 输入:s = "egg", t = "add"输出:true 示例 2: 输入:

数据结构:小白专场:树的同构2程序框架、建树及同构判别

T1T2是之前提到的结构数组,是全局变量,作为参数传进去 调用Ismorphic这个函数判断R1R2是不是同构的 首先考虑如何构建BuidTree函数 输入数据的结构如左图 知道n之后,n不为0,循环,循环一次读入一行数据 为了处理方便,三个信息读入的时候都处理成字符的方式读进来,left和right再把字符处理整数再放到left和right里面去 用了scanf三个%c读入三

【leetcode--同构字符串】

要求:判断两个字符串的形式是不是一致,即是不是AABC或者ABBBCC这种。 trick:使用set()结合zip()。 set()用法:用于创建一个不包含重复元素的集合 zip()用法:用于将可迭代的对象作为参数,将对象中的元素打包成一个个元组,然后返回这些元组组成的对象。 s="abc"t="xyz"zipped = zip(s,t)list_1 = list(zipped)

洛谷 P5043 【模板】树同构([BJOI2015]树的同构)题解 树哈希 树的重心

【模板】树同构([BJOI2015]树的同构) 题目描述 树是一种很常见的数据结构。 我们把 N N N 个点, N − 1 N-1 N−1 条边的连通无向图称为树。 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。 对于两个树 T 1 T_1 T1​ 和 T 2 T_2 T2​,如果能够把树 T 1 T_1 T1​ 的所有点重新标号,使得树 T 1

【同构字符串】python

思路: 先记录同一个值出现的次数,再将字典中的值取出,比较2个列表即可  代码: class Solution:def isIsomorphic(self, s: str, t: str) -> bool:dit1=dict()dit2=dict()for i in range(len(s)):if s[i] not in dit1:dit1[s[i]]=icontinue#记录

高等代数复习:同构定理

文章目录 同构定理 本篇文章适合个人复习翻阅,不建议新手入门使用 同构定理 接下来我们要证明如下几个同构定理 定理(线性映射同构定理) 设 φ : V → V ′ \varphi:V\to V' φ:V→V′ 是一个线性映射,则存在一个自然的线性同构 V / ker ⁡ φ ≅ Im ⁡ φ V/\ker \varphi \cong \operatorname{Im}

求1-10000之间的同构数

“同构数”是指这样的整数:它恰好出现在其平方数的右端。如:376*376=141376。请找出10000以内的全部“同构数” 来自360问答的题目,试着写了写,好歹实现了。 /*总结思路:1.求出1-10000之间每个数的位数(即这个数是几位数)2.再求出每个数的平方值,提取出最右端对应位数的数值出来(如369是个三个数,它的平方是136161,用取模%法提取出最右三位数字161