• CF578F. Mirror Box


    题目大意

    题解

    之前在看PE的Eulerian Circle那题的时候就想过生成树建图+矩阵树计数的问题,并且还想了一些做法,然后全部木大


    结论:将图黑白染色,答案就是黑/白的生成树个数之和

    第二个条件等价于图中无环,生成树即可满足

    第一个条件根据左上第一个格子的情况讨论,发现两种情况刚好对应黑/白的情况,其中一个生成树中的一个块就是一对射线的路径,因为连通块个数最小所以一定相邻(自行画图)

    然后中间的可以唯一确定,因此加起来就是答案

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%mod
    #define ll long long
    //#define file
    using namespace std;
    
    int num[101][101],fa[20001],b[201][2],bz[20001],f[202],n,m,i,j,k,l,mod,Mod,tot,N;
    ll a[202][202],ans;
    char ch;
    
    ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
    int gf(int t) {if (fa[t]==t) return t;fa[t]=gf(fa[t]);return fa[t];}
    void link(int x,int y) {if (gf(x)!=gf(y)) fa[fa[x]]=fa[y]; else {printf("0
    ");exit(0);}}
    
    void work(int s)
    {
    	int i,j,k,l;
    	ll ans=1;
    	
    	memset(bz,0,sizeof(bz));
    	memset(a,0,sizeof(a));
    	memset(f,0,sizeof(f));
    	N=0;
    	fo(i,0,n)
    	{
    		fo(j,0,m)
    		if (((i+j)&1)==s && gf(num[i][j])==num[i][j])
    		bz[num[i][j]]=++N;
    	}
    	
    	if (N>tot+1) return;
    	fo(i,1,tot)
    	{
    		if (((b[i][0]+b[i][1])&1)==s) k=num[b[i][0]-1][b[i][1]-1],l=num[b[i][0]][b[i][1]];
    		else k=num[b[i][0]-1][b[i][1]],l=num[b[i][0]][b[i][1]-1];
    		k=bz[gf(k)],l=bz[gf(l)];
    		if (k!=l) ++a[k][l],++a[l][k];
    	}
    	
    	fo(i,1,N)
    	{
    		fo(j,1,N)
    		if (i!=j)
    		add(a[i][i],a[i][j]),a[i][j]=-a[i][j];
    	}
    	
    	fo(i,1,N-1)
    	{
    		fo(j,1,N-1)
    		if (a[i][j])
    		{
    			if (!f[j])
    			{
    				f[j]=i,ans=ans*a[i][j]%mod,a[i][j]=qpower(a[i][j],Mod);
    				fo(k,j+1,N-1) a[i][k]=a[i][k]*a[i][j]%mod;
    				a[i][j]=1;
    				break;
    			}
    			else
    			{
    				fo(k,j+1,N-1) add(a[i][k],-a[i][j]*a[f[j]][k]);
    				a[i][j]=0;
    			}
    		}
    	}
    	
    	fo(i,1,N-1) if (!f[i]) ans=0;
    	fo(i,1,N-2)
    	{
    		fo(j,i+1,N-1)
    		if (f[i]>f[j])
    		ans=-ans;
    	}
    	add(::ans,ans);
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF578F.in","r",stdin);
    	#endif
    	
    	scanf("%d%d%d",&n,&m,&mod),Mod=mod-2;
    	fo(i,0,n) fo(j,0,m) num[i][j]=i*(m+1)+j+1,fa[num[i][j]]=num[i][j];
    	fo(i,1,n)
    	{
    		fo(j,1,m)
    		{
    			ch=getchar();
    			while (ch!='/' && ch!='\' && ch!='*') ch=getchar();
    			if (ch=='/')  link(num[i-1][j],num[i][j-1]);
    			if (ch=='\') link(num[i-1][j-1],num[i][j]);
    			if (ch=='*') ++tot,b[tot][0]=i,b[tot][1]=j;
    		}
    	}
    	
    	work(0),work(1);
    	printf("%lld
    ",(ans+mod)%mod);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    成功并不是要得到什么,而是要放弃什么
    Qt一步一步实现插件通信(附源码)
    Qt一步一步实现插件调用(附源码)
    推荐大家阅读——《你的知识需要管理》
    移动商机十人谈__移动红利
    如果再不要求进步,那么你就是下一个陨落的巨头
    贫穷的本质__如何改变穷人的现状?
    贫穷的本质__缺乏对未来的信心和长远规划
    痛苦并愉快的被洗着_品牌洗脑
    Qt_Pro详解
  • 原文地址:https://www.cnblogs.com/gmh77/p/13693118.html
Copyright © 2020-2023  润新知