hdu 5278 YJC plays automaton

YJC plays automaton

Accepts: 1

Submissions: 14

Time Limit: 12000/6000 MS (Java/Others)

Memory Limit: 524288/262144 K (Java/Others)

问题描述

YJC是个小火车老司机,所以他是袜子坊烧饼栏目举办的“吃的更圆”竞赛金牌获得者,他去吃特色菜时看到一个n+1个状态的自动机,编号为0到n,其中0号点表示NULL,他非常好奇于是开始了研究:
他选取了一个初始状态集合S,发现其有如下有趣性质:
存在一个字符串str,使得S中的每一个元素在自动机上运行了str之后,得到的结束状态集合包含NULL和至少一个NULL以外的状态,即S中运行str后到达NULL的状态数目在[1,|S|?1]中。
满足这个性质的集合叫做YJC集,注意YJC集不能包含NULL。
他想知道有多少个YJC集。

关于自动机在本题中你可以这样理解:
自动机有n+1个状态,编号0到n,其中0是NULL状态,设字符集大小为m。
有转移函数δ(i,j)(0≤i≤n,1≤j≤m),满足0≤δ(i,j)≤n且δ(0,j)=0
一个状态t在自动机上运行字符串str可以参考以下程序
for  i=0..str.length?1
    t←δ(t,str[i])
你还可以查看
https://zh.wikipedia.org/wiki/自動機理論

输入描述

第一行两个正整数n,m(1≤n≤888,1≤m≤8),表示自动机大小和字符集大小。
以下n行,每行m个元素,表示转移函数δ(i,j),即第i个状态读取到字符j的转移目标,若为0则表示转移到NULL。
NULL只能转移到NULL。

最终测试时,输入文件不超过11000行,共31组。

由于测试时是总时限,若你的程序最坏情况下可以在0.5s内通过1组极限数据(CPU 3.0 GHz),一般可以通过systemtest。

输出描述

一行一个整数,表示YJC集的个数。
答案对998244353(7×17×223+1,一个质数)取模。

输入样例

3 2
3 0
3 0
0 3

输出样例

3

Hint

可能的YJC集有:{1,3},{2,3},{1,2,3}
状态1,2是等价的,显然1,2不是YJC集

思路:建立反向图,先考虑二元组,使用bfs把目的状态能到达的二元组记下来。最后计算答案,好难表述。

/*hdu 5278 YJC plays automaton
  思路:
  建立反向图,先考虑二元组,使用bfs把目的状态能到达的二元组记下来。
  最后计算答案,好难表述。
 */
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define PII pair<int,int>
#define LL __int64
#define MP make_pair
#define PB push_back
#define X first
#define Y second
const int MOD=998244353;
const int N=1005;
const int M=10;
int tran[N][M];
LL two[N];
void predo(){
	two[0]=1;
	for(int i=1;i<N;++i)
		two[i]=two[i-1]*2%MOD;
}

vector<PII> e[N][N];
PII que[N*N];
int front,tail;

int fa[N],num[N];
void init_bcj(){
	for(int i=0;i<N;++i){
		fa[i]=i;
		num[i]=1;
	}
}
int getFa(int x){
	if(x!=fa[x]) return fa[x]=getFa(fa[x]);
	return x;
}
void bin(int x,int y){
	int fx=getFa(x);
	int fy=getFa(y);
	if(fx==fy) return ;
	fa[fy]=fx;
	num[fx]+=num[fy];
	num[fy]=0;
}

int mark=0;
int used[N][N];
void gao(int n,int m){
	++mark;
	for(int i=0;i<=n;++i)
		for(int j=0;j<=n;++j)
			e[i][j].clear();

	for(int x1=0;x1<=n;++x1){
		for(int y1=x1+1;y1<=n;++y1){
			for(int i=0;i<m;++i){
				int x2=tran[x1][i];
				int y2=tran[y1][i];
				if(x2>y2) swap(x2,y2);
				e[x2][y2].PB(MP(x1,y1));
			}
		}
	}
	front=tail=0;
	for(int i=1;i<=n;++i){
		que[tail++]=MP(0,i);
		used[0][i]=mark;
	}
	while(front<tail){
		PII now=que[front++];
		for(int i=0;i<e[now.X][now.Y].size();++i){
			int tmpx=e[now.X][now.Y][i].X;
			int tmpy=e[now.X][now.Y][i].Y;
			if(used[tmpx][tmpy]==mark) continue;
			que[tail++]=MP(tmpx,tmpy);
			used[tmpx][tmpy]=mark;
		}
	}

	init_bcj();
	for(int i=1;i<=n;++i){
		for(int j=i+1;j<=n;++j){
			if(used[i][j]!=mark) bin(i,j);
		}
	}

	LL ans=(two[n]-1+MOD)%MOD;
	for(int i=1;i<=n;++i){
		if(num[i]){
			//cout<<i<<' '<<num[i]<<endl;
			ans=(ans-(two[num[i]]-1)+MOD)%MOD;
		}
	}
	cout<<ans<<endl;

}
int main(){
	predo();
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=1;i<=n;++i)
			for(int j=0;j<m;++j)
				scanf("%d",&tran[i][j]);
		gao(n,m);
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-13 16:24:13

hdu 5278 YJC plays automaton的相关文章

hdu 5279 YJC plays Minecraft——生成函数

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5279 令 n 个点的树的 EGF 是 g(x) ,则 \( g(x) = \sum\limits_{i=0}^{\infty} \frac{i^{i-2}}{i!} x^i \) 令 n 个点的森林的 EGF 是 f(x) ,则 \( f(x) = \sum\limits_{i=0}^{\infty} \frac{g(x)^i}{i!} = e^{g(x)} \) 这道题里,每个团调用 f(x) 的对应

HDU 5279 YJC plays Minecraft (分治NTT优化DP)

题目传送门 题目大意:有$n$个小岛,每个小岛上有$a_{i}$个城市,同一个小岛上的城市互相连接形成一个完全图,第$i$个小岛的第$a_{i}$个城市和第$i+1$个小岛的第$1$个城市连接,特别地,第$n$个小岛的第$a_{n}$个城市和第$1$个小岛的第$1$个城市连接.现在要断掉图中的一些边,保证任意两个城市只有一条路径或者不连通,求合法的断边方案总数,$n,a_{i}<=1e5$ 完全不会(喷血 我们对每个小岛单独讨论 如果任意两个城市只有一条路径或者不连通,那么这张图只能是一个森林

hdu 5277 YJC counts stars

hdu 5277 YJC counts stars 题意: 给出一个平面图,n个点,m条边,直线边与直线边之间不相交,求最大团的数目. 限制: 1 <= n <= 1000 思路: 因为平面图,直线边与直线边之间不相交,所以最大团的大小最大为4,m<=3*n-6. 所以对于答案4,枚举两条边. 对于答案3,枚举一条边一个点. /*hdu 5277 题意: 给出一个平面图,n个点,m条边.直线边与直线边之间不相交,求最大团的数目. 限制: 1 <= n <= 1000 思路:

hdu 5276 YJC tricks time 数学

YJC tricks time Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5276 Description YJC收到了一份神秘礼物.是一个长成这样的钟. YJC不是时间领主所以他并不能乱搞时间,但是这个钟实在是太难认了!所以他想来耍耍你. 现在YJC给你时针和分针间的夹角,让你告诉他现在是什么时候. 你将以以下格式给出可能的时间:HH:MM:SS分别表示小时,分钟

hdu 5277 YJC counts stars 暴力

YJC counts stars Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5277 Description YJC是个老火车小司机.一个晚上,他仰望天空,星辰璀璨,他突然觉得,天空就像一个平面,而每一个星辰,就是平面中的一个点.他把这些点编号为1到n.这些点满足任意三点不共线.他把一些点用线段连起来了,但是任意两条线段不会在端点以外相交.如果一个点的集合中任意两个

HDU 5278 PowMod 数论公式推导

题意:中文题自己看吧 分析:这题分两步 第一步:利用已知公式求出k: 第二步:求出k然后使用欧拉降幂公式即可,欧拉降幂公式不需要互质(第二步就是BZOJ3884原题了) 求k的话就需要构造了(引入官方题解) 然后就求出k了,我就很奇怪为什么是这个式子,然后就网上搜啊搜 找到了一个推导(看完了以后恍然大悟) 推导链接:http://blog.csdn.net/wust_zzwh/article/details/51966450 高度仰慕数学好的巨巨 吐槽:这个题n是无平方因子,然后就要往欧拉函数是

HDU 5277 YJC counts stars (二维平面图求最大团)

题目链接:传送门 题意: 感觉这次读题特别重要啊"这些点满足任意三点不共线.他把一些点用线段连起来了,但是任意两条线段不会在端点以外相交"这是题目给的原话,但是比赛的时候一直没有用...然后就SB了,因为平面图两两相连而且不相交的点集最大就为4,那么就可以分别来考虑了. 首先考虑最大为4的情况,分别枚举两条边,如果这两条边没有公共点,而且顶点两两相连那么就是一个符合的. 如果最大为3的话,那么就可以枚举一条边,然后再枚举点就可以了. 如果最大为2,就输出边数.最大为1的话就输出点的个数

CDQ题目套路总结 [未完成]

CDQ学习资料 day1cdq分治相关 CDQ的IOI论文 1.优化斜率dp 左边对右边影响维护一个凸包解决 需要知识:①凸包②斜率dp 题目:√ HDU3842 Machine Works   HYSBZ 1492 货币兑换Cash 2.三维/多维偏序 cdq降维,剩下用数据结构维护. 需要知识:①LIS②偏序关系③二维线段树/树状数组 题目:陌上花开(此题目前找不到) Pinball Game3D 3.CDQ+FFT/NTT 需要知识:①FFT②NTT 题目:HDU 5730 Shell N

HDU 5882 Balanced Game

Balanced Game Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 508    Accepted Submission(s): 428 Problem Description Rock-paper-scissors is a zero-sum hand game usually played between two people