zoukankan      html  css  js  c++  java
  • poj 2279 Mr. Young's Picture Permutations(杨氏矩阵+钩子公式)

    http://poj.org/problem?id=2279

    题意:
    一共有n个人,要求第i行放置ai个人,且每一行从左往右人的编号递增,每一列从上往下人的编号递增,问有多少种放置方式。

    杨氏矩阵:
    由1——n的n个数组成,对于每一个位置,要么这个位置没有元素,要么这个元素的左方和上方都有元素,且元素的值都小于这个数。

    钩子公式:
    形状确定的杨氏矩阵的个数有 (frac{n!}{prod H(i,j)}) ,其中(H(i,j))表示位置(i,j)下方和右方加上本身一共有多少个元素

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    
    #define N 31
    
    int a[21];
    int p[N],cnt; 
    int tot[N];
    
    bool check(int x)
    {
    	int m=sqrt(x*1.0);
    	for(int i=2;i<=m;++i)
    		if(!(x%i)) return false;
    	return true;
    }
    
    void prep()
    {
    	for(int i=2;i<N;++i)
    		if(check(i)) p[++cnt]=i;
    }
    
    void divide(int x,int y)
    {
    	for(int i=1;i<=cnt && p[i]<=x;++i)
    		while(!(x%p[i]))
    		{
    			x/=p[i];
    			tot[i]+=y;
    		}
    	
    }
    
    int main()
    {
    	prep();
    	int n,m,x,y;
    	while(1)
    	{
    		scanf("%d",&n);
    		if(!n) return 0;
    		m=0;
    		memset(tot,0,sizeof(tot));
    		for(int i=1;i<=n;++i)
    		{
    			scanf("%d",&a[i]);
    			m+=a[i];
    		}
    		for(int i=2;i<=m;++i) divide(i,1); 
    		for(int i=1;i<=n;++i)
    			for(int j=1;j<=a[i];++j)
    			{
    				x=a[i]-j;
    				y=0;
    				for(int k=i+1;k<=n;++k)
    					if(a[k]>=j) ++y;
    				divide(x+y+1,-1);
    			}
    		long long ans=1;
    		for(int i=1;i<=cnt;++i) 
    			while(tot[i])
    			{
    				ans*=p[i];
    				tot[i]--;
    			}
    		printf("%lld
    ",ans);
    	}
    }
    
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    DataGirdView 编辑项时的验证
    存储过程分面
    Android PopupWindow菜单
    Android ListView 中的checkbox
    Linq Group
    final关键字
    BroadcastReceiver
    Android Studio 快捷键
    Android Studio 基础知识
    黑客帝国代码雨实现
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/14751854.html
Copyright © 2011-2022 走看看