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