• bzoj 2729: [HNOI2012]排队


    Description

    某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)

    Solution

    写复杂了
    可以先摆好 (n) 个男同学,再把女同学和老师分别插空,保证不相邻
    发现女生实际是可以先相邻然后再插老师的,所以讨论老师的摆法
    设老师为(T),女生为(G),有 (GTG),(GTGTG) 两种,分别把这个整体当作女生计算一下即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=4010,mod=1e5;
    int n,m,prime[N],pre[N],num=0,cnt[N];
    void priwork(){
    	for(int i=2;i<=n+m+2;i++){
    		if(!pre[i])prime[++num]=i,pre[i]=i;
    		for(int j=1;j<=num && i*prime[j]<=n+m+2;j++){
    			pre[i*prime[j]]=prime[j];
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    inline void add(int x){
    	if(!x)cnt[0]++;
    	while(x>1){
    		cnt[pre[x]]++;
    		x/=pre[x];
    	}
    }
    struct sub{
    	int len,a[N];
    	sub(){memset(a,0,sizeof(a));len=0;}
    	inline void init(){len=0;memset(a,0,sizeof(a));a[++len]=1;}
    	inline void operator *=(const int &t){
    		for(int i=1;i<=len;i++)a[i]*=t;
    		for(int i=1;i<=len;i++)
    			if(a[i]>=mod)a[i+1]+=a[i]/mod,a[i]%=mod;
    		while(a[len+1]){
    			len++;
    			if(a[len]>=mod)a[len+1]+=a[len]/mod,a[len]%=mod;
    		}
    	}
    	inline void operator +=(const sub &t){
    		len=max(len,t.len);
    		for(int i=1;i<=len;i++){
    			a[i]+=t.a[i];
    			if(a[i]>=mod)a[i]-=mod,a[i+1]++;
    		}
    		while(a[len+1]){
    			len++;
    			if(a[len]>=mod)a[len+1]++,a[len]-=mod;
    		}
    	}
    	inline void Print(){
    		printf("%d",a[len]);
    		for(int i=len-1;i>=1;i--)
    			for(int j=mod/10;j;j/=10)
    				printf("%d",a[i]/j),a[i]%=j;
    		puts("");
    	}
    };
    int main(){
    	freopen("pp.in","r",stdin);
    	freopen("pp.out","w",stdout);
    	cin>>n>>m;
    	priwork();
    	for(int i=n-m+2;i<=n+1;i++)add(i);
    	for(int i=1;i<=n;i++)add(i);
    	add(n+m);add(n+m+1);
    	sub ans,t;
    	t.init();
    	for(int i=0;i<=n+m+2;i++)
    		for(int j=1;j<=cnt[i];j++)t*=i;
    	ans+=t;
    	memset(cnt,0,sizeof(cnt));t.init();
    	for(int i=1;i<=n;i++)add(i);
    	for(int i=n-m+3;i<=n+1;i++)add(i);
    	add(m);add(m-1);add(n+m);add(2);
    	for(int i=0;i<=n+m+2;i++)
    		for(int j=1;j<=cnt[i];j++)t*=i;
    	ans+=t;
    	memset(cnt,0,sizeof(cnt));t.init();
    	for(int i=1;i<=n;i++)add(i);
    	for(int i=n-m+4;i<=n+1;i++)add(i);
    	add(m);add(m-1);add(m-2);add(m-1);
    	for(int i=0;i<=n+m+2;i++)
    		for(int j=1;j<=cnt[i];j++)
    			t*=i;
    	ans+=t;
    	ans.Print();
    	return 0;
    }
    
    
  • 相关阅读:
    怎么样实现打印网页中指定的表格,而不是全页
    加深C# 中字符串前加@符号理解以及使用~~
    CommandArgument 绑定多个参数
    gridview等控件CommandField英文的解决.
    正式发布基于VS2008的AJAX模板包
    给datalist加自动编号
    .net生成文字图片
    重新注册.net
    Android JNI入门第二篇——Java参数类型与本地参数类型对照
    Android推送方式比较
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8460460.html
Copyright © 2020-2023  润新知