「PKUWC 2018」随机算法 (60分部分分做法)

明天就是CTSC的DAY 2了qwq,晚上敲敲暴力攒攒RP,果断随便看了个题就是打暴力hhhhh

前50% O(3^N) 暴力没什么好说的,我们设F[S][s]为已经选了S集合中的点,并且这个集合中的点的最大独立集是s的方案数,最后统计完了乘上 n! 的逆元就好了。  (s肯定是S的一个子集,所以复杂度是 3^n)

然鹅中间的暴力分只会链。。。。。

首先如果n是奇数的话,那么最大独立集只可能是所有奇数点,所有这种情况下我们知道了选了的点的集合就知道独立集是什么了,所以可以直接 O(2^n) dp了。。。。

但是出题人并没有这么良心2333,这一个点的n在最后的数据里是偶数。。。。

考虑如果n是偶数的情况的话,独立集只可能是:全是奇数的点 或者 全是偶数的点 或者 ∑ [i是偶数] <=i的全是奇数的点 和 >i的全是偶数的点,这样的话我们先用 与求n是奇数的同样的方法 (钦定最大独立集是所有奇数点) 求出对于每个偶数i,最大独立集是<=i的奇数的点的答案,然后卷积合并一下就好啦,因为后面的全是偶数的点的集合可以看成是反向的全是奇数的点的集合。

合并的时候还要乘上一个组合数,因为两边元素之间的顺序还没有确定、

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=300005,ha=998244353;
inline int add(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha; return an;}
unordered_map<int,int> f[maxn];
unordered_map<int,int>:: iterator it;
int n,ci[35],m,uu,vv,BC[maxn],ans,M;
bool G[35][35],can[maxn][23];
inline int ADD(int S,int x){ return can[S][x]?(S|ci[x]):S;}
int g[maxn*4+5],jc[233],C[233][233];

inline void init(){
	for(int i=0;i<ci[n];i++)
	    for(int j=0;j<n;j++) if(!(ci[j]&i)){
	    	can[i][j]=1;
	    	for(int o=0;o<n;o++) if((ci[o]&i)&&G[o][j]){
	    		can[i][j]=0;
	    		break;
			}

		}
}

inline void calc(){
	ans=ans*(ll)ksm(jc[n],ha-2)%ha;
}

inline void solve(){
	f[0][0]=1; int all=ci[n]-1;

	for(int i=0;i<all;i++)
	    for(it=f[i].begin();it!=f[i].end();++it)
	        for(int j=0,S,to;j<n;j++) if(!(ci[j]&i)){
	        	S=i|ci[j],to=ADD(it->first,j),M=max(M,BC[to]);
	        	add(f[S][to],it->second);
			}

	for(it=f[all].begin();it!=f[all].end();++it) if(BC[it->first]==M) add(ans,it->second);
}

inline int get_line(int N){
	memset(g,0,sizeof(g));
	g[0]=1; int all=ci[N]-1;

	for(int i=0;i<all;i++) if(g[i])
	    for(int j=0;j<N;j++) if(!(ci[j]&i)){
	    	if((j&1)&&!((i&ci[j-1])||(i&ci[j+1]))) continue;

	        add(g[i|ci[j]],g[i]);
	    }
	return g[all];
}

inline void qwqwq(){
	int o[23];
	for(int i=2;i<=n;i+=2) o[i]=get_line(i);
	add(ans,o[n]),add(ans,o[n]);

	for(int i=2;i<n;i+=2) add(ans,o[i]*(ll)o[n-i]%ha*C[n][i]%ha);
}

int main(){
	ci[0]=1;
	for(int i=1;i<=20;i++) ci[i]=ci[i-1]<<1;
	jc[0]=1;
	for(int i=1;i<=20;i++) jc[i]=jc[i-1]*(ll)i%ha;
	C[0][0]=1;
	for(int i=1;i<=75;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++) add(C[i][j],C[i-1][j-1]),add(C[i][j],C[i-1][j]);
	}

	scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d",&uu,&vv),G[uu-1][vv-1]=G[vv-1][uu-1]=1;

	if(n<=17){
		for(int i=1;i<ci[n];i++) BC[i]=BC[i^(i&-i)]+1;
	    init(),solve();
    }
    else if(n&1) ans=get_line(n);
    else qwqwq();

    calc();

	printf("%d\n",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/9011613.html

时间: 2024-11-06 11:37:24

「PKUWC 2018」随机算法 (60分部分分做法)的相关文章

「PKUWC2018」随机算法

传送门 Description 我们知道,求任意图的最大独立集是一类NP完全问题,目前还没有准确的多项式算法,但是有许多多项式复杂度的近似算法. 例如,小 C 常用的一种算法是: 对于一个 \(n\) 个点的无向图,先等概率随机一个 $1\ldots n $的排列 \(p[1\ldots n]\). 维护答案集合 \(S\),一开始 \(S\) 为空集,之后按照 \(i=1\ldots n\) 的顺序,检查 \(\{p[i]\}\cup S\) 是否是一个独立集,如果是的话就令 \(S=\{p[

loj#2540. 「PKUWC2018」随机算法

传送门 完了pkuwc咋全是dp怕是要爆零了-- 设\(f(S)\)表示\(S\)的排列数,\(S\)为不能再选的点集(也就是选到独立集里的点和与他们相邻的点),\(mx(S)\)表示\(S\)状态下对应的独立集大小,枚举点\(i\),如果\(i\)不在\(S\)里,分情况考虑,设\(w[i]\)表示点\(i\)以及与之相邻的点,\(T=S|w[i]\),\(sz[S]\)表示二进制\(S\)有多少个\(1\),如果\(mx[T]=mx[S]+1\),那么\[f[T]+=f[S]\times A

「Luogu4321」随机游走

「Luogu4321」随机游走 题目描述 有一张 \(n\) 个点 \(m\) 条边的无向图,\(Q\) 组询问,每次询问给出一个出发点和一个点集 \(S\) ,求从出发点出发随机游走走遍这个点集的期望步数. \(1 \leq n \leq 18, 1 \leq Q \leq 10^5\) 解题思路 : 听说是 \(\text{pkuwc2018d2t3}\) 加强版?但是原题时限是1s,各种卡不进去感觉一定要写 \(\text{Min-Max}\) 容斥,不过反正我今年听指导建议没报 \(\t

Loj #2542. 「PKUWC2018」随机游走

Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次询问给定一个集合 \(S\),求如果从 \(x\) 出发一直随机游走,直到点集 \(S\) 中所有点都至少经过一次的话,期望游走几步. 特别地,点 \(x\)(即起点)视为一开始就被经过了一次. 答案对 $998244353 $ 取模. 输入格式 第一行三个正整数 \(n,Q,x\). 接下来 \(

PKUSC 2018 随机算法

PKUSC 2018 随机算法 \[ made \ by \ Ameiyo \] 题目连接 用 $ f[i][s] $ 表示已经有 $ i $ 个点在排列里面,最大独立集的集合为 $ s $ ,这样的方案数. 对于当前不能加入最大独立集的点,在之后仍然不能加入,所以这些点可以被视为相同点,当做消耗品一样使用即可. 而可以加入的点,即加入后会使最大独立集变大的点,就直接放进 $ s $ 就行了. #include <cstdio> #include <cctype> #include

深度 | 邢波教授谈人工智能科学路径:为人工智能装上「无穷动」引擎

深度 | 邢波教授谈人工智能科学路径:为人工智能装上「无穷动」引擎 本文由邢波教授 授权转载 微信公众号:猫匣子 作者:邢波 有些人是因为对人工智能的原理不理解而导致,有些人是为了个人名望而宣扬人工智能威胁论,有些人则是为了商业的利益推动人工智能威胁论.——Yann LeCun   人工智能算法本身这个计算任务像登山,它是有明确的目标的,可以用数学描述和比较的目标,它本身有弹性.容错性.随机性.和客观的量化的可评估性 … 人工智能功能的提升和突破来源于理论模型,算法,和计算引擎的不断创新,缺一不

ERNIE:知识图谱结合BERT才是「有文化」的语言模型

自然语言表征模型最近受到非常多的关注,很多研究者将其视为 NLP 最重要的研究方向之一.例如在大规模语料库上预训练的 BERT,它可以从纯文本中很好地捕捉丰富的语义模式,经过微调后可以持续改善不同 NLP 任务的性能.因此,我们获取 BERT 隐藏层表征后,可用于提升自己任务的性能. 但是,已有的预训练语言模型很少考虑知识信息,具体而言即知识图谱(knowledge graphs,KG),知识图谱能够提供丰富的结构化知识事实,以便进行更好的知识理解.简而言之,预训练语言模型只知道语言相关的「合理

「圣诞特辑」纯前端实现人脸识别自动佩戴圣诞帽

在线体验地址:hksite.cn/prjs/christmashat 源码地址:https://github.com/hk029/christmas-hat 写在开头 叮叮当,叮叮当,吊儿个郎当,一年一度的圣诞节到咯,我不由的回想起了前两年票圈被圣诞帽支配的恐惧.打开票圈全是各种@官方求帽子的: 票圈头像也瞬间被圣诞帽攻陷: 在那段时间,你没一顶圣诞帽还真不好意思发票圈 各种戴帽子的软件也如雨后春笋般浮现出来,不管是小程序还是美图软件无一例外的都增加了戴圣诞帽的功能.但是对于懒人的我来说,自己调

怎样将「插件化」接入到项目之中?

本期移动开发精英社群讨论的主题是「插件化」,上网查了一下,发现一篇 CSDN 博主写的文章<Android 使用动态载入框架DL进行插件化开发>.此处引用原作者的话: 随着应用的不断迭代,应用的体积不断增大,项目越来越臃肿,冗余添加.项目新功能的加入,无法确定与用户匹配性,发生严重异常往往牵一发而动全身,仅仅能紧急公布补丁版本号,强制用户进行更新.结果频繁的更新.反而easy减少用户使用黏性,或者是公司业务的不断发展,同系的应用越来越多,传统方式须要通过用户量最大的主项目进行引导下载并安装.