[组合数学][计数DP]JZOJ 4254 集体照

Description

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

Input

输入文件名为photo.in。
第一行为为一个整数n。
第二行为n个正整数,分别为每个班的人数。

Output

输出文件photo.out,共1行,为总方案数。

Sample Input

输入1:
2
1 2
输入2:
2 
1 3
输入3:
3 
1 2 3
 

Sample Output

输出1:
2
输出2:
0
输出3:
120

Data Constraint

对于30%,Sigma(Ai) <=10
对于另外10%,n=2
对于另外20%,n=3
对于100%,1<=n<=50,1<=Ai<=50, Sigma(Ai)<=1500

分析

组合数学题日常博客跳转

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=5e2+10;
const int Sigma=1.5e3+10;
const ll P=1e9+7;
int n;
ll a[N],s[N],fact[N],C[Sigma][Sigma],f[N][Sigma];

int main() {
    freopen("photo.in","r",stdin);freopen("photo.out","w",stdout);
    scanf("%d",&n);
    fact[0]=C[0][0]=1;
    for (int i=1;i<N;i++) fact[i]=fact[i-1]*i%P;
    for (int i=1;i<Sigma;i++)
        for (int j=0;j<=i;j++)
            C[i][j]=(C[i-1][j]+(j?C[i-1][j-1]:0))%P;
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]),s[i]=s[i-1]+a[i];
    f[1][s[1]-1]=1;
    for (int i=2;i<=n;i++)
        for (int j=0;j<=s[i-1];j++)
            if (f[i-1][j])
                for (int k=1;k<=a[i];k++)
                    for (int t=0;t<=min(k,j);t++)
                        (f[i][j+a[i]-k-t]+=f[i-1][j]*C[j][t]%P*C[a[i]-1][k-1]%P*C[s[i-1]+1-j][k-t]%P)%=P;
    for (int i=1;i<=n;i++) (f[n][0]*=fact[a[i]])%=P;
    printf("%lld\n",f[n][0]);
}

原文地址:https://www.cnblogs.com/mastervan/p/10339738.html

时间: 2024-10-02 21:28:14

[组合数学][计数DP]JZOJ 4254 集体照的相关文章

Ant Counting POJ 3046(计数dp)

原题 题目链接 题目分析 计数dp题,感觉其实也可以用组合数学做,但我太菜了,推不出通用公式.dp可以定义dp[i][j]为前i种选j个蚂蚁有多少种选法,然后递推公式如下,其中c[i]表示第i种的数量, dp[i][j]=Σ(min(j,c[i]),k=0)dp[i-1][j-k].可以化简一下,dp[i][j]=∑(c[i],k=0)dp[i-1][j-1-k]+dp[i-1][j]-dp[i-1][j-1-c[i]],最后答案就是dp[t][s]+dp[t][s+1]+...+dp[t][b

HDU4815/计数DP

题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=4815] 简单说一下题意: 有n道题,每到题答对得分为a[ i ],假如A不输给B的最小概率是P,那么A最少要得到多少分. 解题过程: 假设有n道题,每个题有两个状态,胜或者败,假设达到某个分数m有k(计数DP)种方式,那么最后是这个分数的概率是k/pow(2,n).那么A不输给B的概率就是小于等于m的分数的概率和. #include<bits/stdc++.h> const int maxn =

[sdut]2879计数dp……或者递推

第五届省赛C:colourful cupcakes N=60. 天真如我,居然在考虑搜索的算法/(ㄒoㄒ)/~~三叉树……3^60=10^24+……不计算考虑复杂度都是耍流氓>_< 再算了一下,感觉O(N^4)可以试试,60^4=10^8+……但是毕竟最差的情况嘛>_<,再看一下题解果然是4重循环的……计数……dp……(想到之前坚信的搜索不禁(*/ω\*)) 中间看到了一个三次动规六个方程的算法. 做麻烦了. 学长思路好快. #include<iostream> #in

HDU4901 The Romantic Hero 计数DP

2014多校4的1005 题目:http://acm.hdu.edu.cn/showproblem.php?pid=4901 The Romantic Hero Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 393    Accepted Submission(s): 150 Problem Description There i

[计数dp] ural 1114. Boxes

题目链接: http://acm.timus.ru/problem.aspx?space=1&num=1114 1114. Boxes Time limit: 0.6 second Memory limit: 64 MB N boxes are lined up in a sequence (1 ≤ N ≤ 20). You have A red balls and B blue balls (0 ≤ A ≤ 15, 0 ≤ B ≤ 15). The red balls (and the blu

ACM/ICPC算法训练 之 数学很重要-浅谈“排列计数” (DP题-POJ1037)

这一题是最近在看Coursera的<算法与设计>的公开课时看到的一道较难的DP例题,之所以写下来,一方面是因为DP的状态我想了很久才想明白,所以借此记录,另一方面是看到这一题有运用到 排列计数 的方法,虽然排列计数的思路简单,但却是算法中一个数学优化的点睛之笔. Poj1037  A decorative fence 题意:有K组数据(1~100),每组数据给出总木棒数N(1~20)和一个排列数C(64位整型范围内),N个木棒长度各异,按照以下条件排列,并将所有可能结果进行字典序排序 1.每一

CodeForces 176B Word Cut (计数DP)

Word Cut Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 176B Description Let's consider one interesting word game. In this game you should transform one word into another through specia

SPOJ ANARC05H 计数DP

给定一个数字串,问有多少种拆分方法,题目所谓的拆分,就是分成若干个子块,每个块的和 即为各个数字相加,当前块的和一定要小于等于后面的块的和 比如1117  就有这些[1-117], [1-1-17], [1-11-7], [1-1-1-7], [11-17],and [111-7] 肯定是计数DP,而且二维即可,不过第二维应该怎么设置是亮点,我也想了好多种方案,不过都被否定了,后来还是一种其实比较经典的方案进来了,就是代表当前最后一个块的和是多少,则当前dp[i][j] 由dp[i-1][k]转

hdu 4901 The Romantic Hero(计数dp)2014多校训练第4场1005

The Romantic Hero                                                                               Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is an old country and the king fell in lov