zoukankan      html  css  js  c++  java
  • ARC107C Shuffle Permutation【有脑就行qwq/完全不知道怎么分类嘛】

    题目链接

    其实也不是挺难吧,但是就是没有做出来啊(忧伤

    最可怕的是读完题之后大脑一片空白,没有任何想法

    题目解析

    首先,行和列是独立的,我们分别算出行和列的方案然后再相乘就可以了,而且由于行和列具有对称性(是这个词,吧),所以算行和列的算法是一样的。

    考虑到,如果(x,y)可以交换,(y,z)可以交换,那么(x,z)可以交换(具有传递性):

    (x,y,z->y,x,z->y,z,x->z,y,x)

    所以我们每找到一对符合条件,就把它们并查集一下,做完之后同一个连通块里的位置是可以互通有无的(是这个词,吧),就是说这(s)个位置可以随便放这(s)个点,假设这个块的大小是(s),那么这个块里进行操作有(s!)种方案(矩形里每个数都不一样)

    不同块之间用乘法原理。

    然后我并查集还写挂了一下,就是(f[i])不一定是(i)这一个块的“首领”,要(find)一下。


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<string>
    #include<map>
    #include<cmath>
    using namespace std;
    #define N 55
    #define MOD 998244353
    #define LL long long
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
    	return f*x;
    }
    int n,k;
    int a[N][N],f[N],siz[N];
    void Init()
    {
    	for(int i=1;i<=n;i++)
    		f[i]=i;
    }
    int Find(int x)
    {
    	if(f[x]==x) return x;
    	return f[x]=Find(f[x]);
    }
    void Union(int x,int y)
    {
    	x=Find(x),y=Find(y);
    	if(x==y) return ;
    	if(x<y) f[x]=y;
    	else f[y]=x;
    }
    LL fac(int x)
    {
    	if(x==0||x==1) return 1;
    	LL res=1ll;
    	for(int i=2;i<=x;i++)
    		res=1ll*res*i%MOD;
    	return res;
    }
    int main()
    {
    	n=rd(),k=rd();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			a[i][j]=rd();
    	Init();
    	for(int x=1;x<=n;x++)
    		for(int y=x+1;y<=n;y++)
    		{
    			bool flag=0;
    			for(int i=1;i<=n;i++)
    				if(a[i][x]+a[i][y]>k)
    				{
    					flag=1;
    					break;
    				}
    			if(!flag) Union(x,y);
    		}
    	LL ans=1ll;
    	for(int i=1;i<=n;i++)
    		siz[Find(f[i])/*之前这里写的f[i]qwq*/]++;
    	for(int i=1;i<=n;i++)
    		ans=ans*fac(siz[i])%MOD;//ans=(ans+fac(siz[i]))%MOD;
    	//几种情况之间不是replacalbe的关系 而是分步进行 所以应该用乘法 
    	
    	Init();
    	memset(siz,0,sizeof(siz)); 
    	for(int x=1;x<=n;x++)
    		for(int y=x+1;y<=n;y++)
    		{
    			bool flag=0;
    			for(int i=1;i<=n;i++)
    				if(a[x][i]+a[y][i]>k)
    				{
    					flag=1;
    					break;
    				}
    			if(!flag) Union(x,y);
    		}
    	LL res=1ll;
    	for(int i=1;i<=n;i++)
    		siz[Find(f[i])]++;
    	for(int i=1;i<=n;i++)
    		res=res*fac(siz[i])%MOD;//res=(res+fac(siz[i]))%MOD;
    	//printf("%lld %lld
    ",ans,res);
    	printf("%lld
    ",ans*res%MOD);
        return 0;
    }
    
  • 相关阅读:
    抽奖代码
    org.hibernate.AssertionFailure: null id in com.you.model.User entry (don't flush the Session after a
    Cannot add or update a child row: a foreign key constraint fails
    SyntaxError:identifier starts immediately after numeric literal
    too much recursion
    微信处理红包
    minerd
    minerd
    kill常用
    阿里云centos 6安装Nginx+PHP+MySQL
  • 原文地址:https://www.cnblogs.com/lyttt/p/13914630.html
Copyright © 2011-2022 走看看