CodeChef Little Elephant and Movies [DP 排列]

https://www.codechef.com/FEB14/problems/LEMOVIE

题意:

对于一个序列,定义其“激动值”为序列中严格大于前面所有数的元素的个数。
给定n个数p1;,p2... pn,求这n个数的所有排列中,激动值不超过k的个数。$1 k \le n \le 200,1 \le pi \le 200$



这种题有一个很神的想法:

把排列按某种顺序往里插入,使得后不会影响前

对于本题,先离散化去重后,从大到小插入,后插入的元素不会影响已经插入的元素严格大于前面所有数

$f[i][j]$表示插入了前$i$大的数,激动值为$j$的方案数

激动值改变只有可能是当前要插入的数中有一个放在了最前面

转移时分类讨论有没有数插在最前面,需要用到隔板法,

设已经插入$x$个数,第$i$大的有$y$个数

$f(i,j)=f(i-1,j)*\binom{x+y-1}{x-1}*{y!}\ +\ f(i-1,j-1)*\binom{x+y-1}{x}*{y!}$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=205,INF=1e9+5,P=1e9+7;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
int n,k,a[N];
int m,d[N],s[N];
inline bool cmp(int a,int b){return a>b;}
ll c[N][N],fac[N];
inline void mod(ll &x){if(x>=P) x-=P;}
void ini(){
    c[0][0]=1;fac[0]=1;
    for(int i=1;i<=200;i++){
        c[i][0]=1;
        for(int j=1;j<=i;j++) mod(c[i][j]+=c[i-1][j]+c[i-1][j-1]);
        fac[i]=fac[i-1]*i%P;
    }
}
ll f[N][N];
void dp(){
    f[0][0]=1;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=k;j++){
            int x=s[i-1],y=d[i];
            f[i][j]=f[i-1][j]*c[x+y-1][x-1]%P*fac[y]%P;
            mod(f[i][j]+=f[i-1][j-1]*c[x+y-1][x]%P*fac[y]%P);
            //printf("f %d %d %lld\n",i,j,f[i][j]);
        }
    ll ans=0;
    for(int i=1;i<=k;i++) mod(ans+=f[m][i]);
    printf("%lld\n",ans);
}
int main(){
    freopen("in","r",stdin);
    ini();
    int T=read();
    while(T--){
        memset(d,0,sizeof(d));
        n=read();k=read();
        for(int i=1;i<=n;i++) a[i]=read();
        sort(a+1,a+1+n,cmp);
        m=0;
        d[++m]=1;
        for(int i=2;i<=n;i++){
            if(a[i]==a[i-1]) d[m]++;
            else d[++m]=1;
        }
        for(int i=1;i<=m;i++) s[i]=s[i-1]+d[i];
        //for(int i=1;i<=m;i++) printf("%d ",d[i]);puts("");
        //for(int i=1;i<=m;i++) printf("%d ",s[i]);puts("");
        dp();
    }
}
时间: 2024-10-12 13:41:10

CodeChef Little Elephant and Movies [DP 排列]的相关文章

CodeChef Little Elephant and Mouses [DP]

https://www.codechef.com/problems/LEMOUSE 题意: 有一个n *m的网格.有一头大象,初始时在(1,1),要移动到(n,m),每次只能向右或者向下走.有些格子中有老鼠,如果大象所在的格子和某个有老鼠的格子的曼哈顿距离$\e$1,大象就会被那只老鼠吓到.求一条移动路径,使得吓到过大象的老鼠数量最少.n;m $\le$100. 开始刷济南集训hzc的课件啦! 最简单的一道$DP$ 一只老鼠只会吓大象一次$f[i][j][0/1]$记录从左还是上走来的,转移时讨

codechef Little Elephant and Permutations题解

The Little Elephant likes permutations. This time he has a permutation A[1], A[2], ..., A[N] of numbers 1, 2, ...,N. He calls a permutation A good, if the number of its inversions is equal to the number of its local inversions. The number of inversio

【BZOJ】4559: [JLoi2016]成绩比较 计数DP+排列组合+拉格朗日插值

[题意]n位同学(其中一位是B神),m门必修课,每门必修课的分数是[1,Ui].B神碾压了k位同学(所有课分数<=B神),且第x门课有rx-1位同学的分数高于B神,求满足条件的分数情况数.当有一位同学的一门必修课分数不同时视为两种情况不同.n,m<=100,Ui<=10^9. [算法]计数DP+排列组合+拉格朗日插值 [题解]把分数作为状态不现实,只能逐门课考虑. 设$f[i][j]$表示前i门课,有j个同学被碾压的情况数,则有: $$f[i][j]=g(i)\cdot\sum_{k=j

HDU--5396(区间dp+排列组合)

做这道题的时候,想到会不会是dp,然后发现dp可做,但是一直被自己坑到死. 枚举最后合并的那个位置,然后对于加减号的,分成的前后两个部分都有不同的组合方法, (a1+a2........) +  (b1,b2.............)         对于每个a,被加b的个数的阶乘次 ,对于每个b,被加a的个数的阶乘次 减法同理 乘法特殊一点 (a1+a2........) *  (b1,b2.............)  乘法分配率,直接将两部分的总和相乘即可 想到这些还远远没有结束,因为最

【noi 2.6_9288】&amp;【hdu 1133】Buy the Ticket(DP / 排列组合 Catalan+高精度)

题意:有m个人有一张50元的纸币,n个人有一张100元的纸币.他们要在一个原始存金为0元的售票处买一张50元的票,问一共有几种方案数. 解法:(学习了他人的推导后~) 1.Catalan数的应用7的变形.(推荐阅读:http://www.cnblogs.com/chenhuan001/p/5157133.html).P.S.不知我之前自己推出的公式“C(n,m)*C(2*m,m)/(m+1)*P(n,n)*P(m,m)”是否是正确的. (1)在不考虑m人和n人本身组内的排列时,总方案数为C(m+

LightOJ1005 Rooks(DP/排列组合)

题目是在n*n的棋盘上放k个车使其不互相攻击的方案数. 首先可以明确的是n*n最多只能合法地放n个车,即每一行都指派一个列去放车. dp[i][j]表示棋盘前i行总共放了j个车的方案数 dp[0][0]=1 转移就是从第i-1行转移到第i行,对于第i行要嘛放上一个车要嘛不放,放的话有n-j-1种方法.即dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(n-j-1). 1 #include<cstdio> 2 #include<cstring> 3 using na

CF 258B Little Elephant and Elections [dp+组合]

给出1,2,3...m 任取7个互不相同的数a1,a2,a3,a4,a5,a6,a7 一个数的幸运度是数位上4或7的个数 比如244,470幸运度是2. 44434,7276727,4747,7474,幸运度都是4. 求出满足a1,a2,a3,a4,a5,a6,a7这样的前6个数的幸运度之和严格小于第七个数的幸运度排列共有多少种 1.先求出数组t t[i]代表1-m中幸运度为i的数的个数. 2.有了t数组后,问题变为一个排列组合问题(枚举a7幸运度,求有多少排列满足前6幸运度之和小于a7幸运度,

HDU 5434 Peace small elephant 状压dp+矩阵快速幂

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: 108 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他

【HDU】5151 Sit Sit Sit(区间DP+排列组合)

题目大意:可以查阅网站的中文翻译,就不说了,是第24场Best Coder 思路: 这道这道区间DP,我也开始觉得其实区间DP是一种应用型的思想,做这类题目一个重要的点是在于题目情景的把握,这道题的一个情景就是数学的排列组合问题. 首先应用根据小区间推出大区间的思路,我们可以先固定一个位置k,k位置是最后做的位置,那么我们要算出在这种情况下符合的方法数,假如k是头或者尾,那不用说, 此时的方法为dp[i+1][j]或者是dp[i][j-1]; 假如k是有邻居的,那我们就要考虑邻居的颜色,如果颜色