• JZOJ 4872.集体照


    ( ext{Problem})

    一年一度的高考结束了,我校要拍集体照。本届毕业生共分 (n) 个班,每个班的人数为 (A_i)。这次拍集体照的要求非常奇怪:所有学生站一排,且相邻两个学生不能同班。现在,安排这次集体照的老师找到了你,想问问你一共有多少种方案。方案数可能很大,最终结果对 (10^9+7) 取模。

    ( ext{Solution})

    考虑 (dp),按班级做,插入人
    (f_{i,j}) 表示做到第 (i) 个班,已经出现 (j) 对相邻
    那么转移就是当前班分 (k) 组,选 (t) 组插到 (j) 个空中,使他们分离

    ( ext{Code})

    #include<cstdio>
    #include<algorithm>
    #define LL long long 
    #define re register
    using namespace std;
    
    const LL P = 1e9 + 7;
    int n, a[55], sum[55];
    LL fac[1505], C[1505][1505], f[55][1505];
    
    inline void ADD(LL &x, LL y)
    {
    	x += y;
    	if (x > P) x -= P;
    }
    
    int main() 
    {
    	freopen("photo.in", "r", stdin);
    	freopen("photo.out", "w", stdout);
    	scanf("%d", &n);
    	for(re int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i];
    	fac[0] = 1;
    	for(re int i = 1; i <= sum[n]; i++) fac[i] = fac[i - 1] * i % P;
    	for(re int i = 0; i <= sum[n]; i++) C[i][0] = 1;
    	for(re int i = 1; i <= sum[n]; i++)
    		for(re int j = 1; j <= i; j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % P;
    	f[1][a[1] - 1] = 1;
    	for(re int i = 2; i <= n; i++)
    		for(re int j = 0; j < sum[i - 1]; j++)
    			for(re int k = 1; k <= a[i]; k++) 
    				for(re int t = 0; t <= k; t++)
    					ADD(f[i][j + a[i] - k - t], f[i - 1][j] * C[a[i] - 1][k - 1] % P * C[j][t] % P * C[sum[i - 1] + 1 - j][k - t] % P);
    	LL ans = f[n][0];
    	for(re int i = 1; i <= n; i++) ans = ans * fac[a[i]] % P;
    	printf("%lld
    ", ans);
    }
    
  • 相关阅读:
    基于springboot框架的博客系统
    告别并不遥远的儿时,抬眼期待未来
    Python微信公众号教程基础篇——收发文本消息
    华为云落地敏捷+DevOps,助力大企业高效能
    【nodejs原理&源码赏析(5)】net模块与通讯的实现
    华为云&华中大联合实验室,夺得2019ICDAR发票识别竞赛世界第一
    00034_类与对象
    php批量下载文件
    php批量下载图片
    asp.net批量下载文件
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15127488.html
Copyright © 2020-2023  润新知