动态规划(计数DP):JLOI 2016 成绩比较

Description

G系共有n位同学,M门必修课。这N位同学的编号为0到N-1的整数,其中B神的编号为0号。这M门必修课编号为0到M-

1的整数。一位同学在必修课上可以获得的分数是1到Ui中的一个整数。如果在每门课上A获得的成绩均小于等于B获

得的成绩,则称A被B碾压。在B神的说法中,G系共有K位同学被他碾压(不包括他自己),而其他N-K-1位同学则没

有被他碾压。D神查到了B神每门必修课的排名。这里的排名是指:如果B神某门课的排名为R,则表示有且仅有R-1

位同学这门课的分数大于B神的分数,有且仅有N-R位同学这门课的分数小于等于B神(不包括他自己)。我们需要

求出全系所有同学每门必修课得分的情况数,使其既能满足B神的说法,也能符合D神查到的排名。这里两种情况不

同当且仅当有任意一位同学在任意一门课上获得的分数不同。你不需要像D神那么厉害,你只需要计算出情况数模1

0^9+7的余数就可以了。

Input

第一行包含三个正整数N,M,K,分别表示G系的同学数量(包括B神),必修课的数量和被B神碾压的同学数量。第二

行包含M个正整数,依次表示每门课的最高分Ui。第三行包含M个正整数,依次表示B神在每门课上的排名Ri。保证1

≤Ri≤N。数据保证至少有1种情况使得B神说的话成立。N<=100,M<=100,Ui<=10^9

Output

仅一行一个正整数,表示满足条件的情况数模10^9+7的余数。

Sample Input

3 2 1

2 2

1 2

Sample Output

10

  首先发现对于n个确定排名的人,分数和其排名无关,这里可以分开处理。

  有两种做法,第一种我分成三个集合,1:我 2:分数小于等于我的3:分数大于等于我的。

  设f[i]表示完虐至少i人,三个集合内无名次顺序的方案数,可以发现容斥是能很好地解决这个分问题的。

  转移是f[i]=C(n-1,i)*Σj=1,j<=mC(n-i-1,r[j]-1)-Σj=i+1,j<=nf[j]*C(j,i) 这个很容易推得。

  然后发现每门的得分情况互不相关,符合乘法原理,我们分开处理,设当前科目排名r,得分上限u,我的得分是x。方案数是 xn-r(u-x)r-1 但是u太大了,x的取值是[1,u],不可能枚举得来,还得分析。

  设t[x]=xn-r(u-x)r-1

  =xn-r *(C(r-1,r-1)*ur-1-C(r-1,r-2)*ur-2*x+……+C(r-1,0)*xr-1)

  =C(r-1,r-1)*ur-1*xn-r-C(r-1,r-2)*ur-2*xn-r+1+……+C(r-1,0)*xn-1

  x=1:请自动脑补

  x=2:请自动脑补

  x=3:请自动脑补

  ……

  x=u:请自动脑补

  设g[k]=1k+2k+3k+……+uk

  Σx=1,x<=ut[x]=C(r-1,r-1)*ur-1*g[n-r]-C(r-1,r-2)*ur-2*xn-r+1*g[n-r+1]+……+C(r-1,0)*xn-1*g[n-1]

  现在只要知道如何求g[k],考虑递推。

  发现设p[a+1]=(a+1)k=C(k,k)*ak+C(k,k-1)*ak-1+……+C(k,0)*a0

  Σa=1,a<=up[a+1]=g[k]+(u+1)k-1=C(k,k)*g[k]+C(k,k-1)*g[k-1]+……+C(k,0)*g[0]

  可以由 (u+1)k-1=C(k,k-1)*g[k-1]+……+C(k,0)*g[0]

  移项得 g[k-1]=(u+1)k-1-(C(k,k-2)*g[k-2]+C[k,k-3]*g[k-3]+……+C[k,0]*g[0])

  用k=k+1替入得:g[k]=(u+1)k+1-1-(C(k+1,k-1)*g[k-1]+C[k+1,k-2]*g[k-2]+……+C[k+1,0]*g[0])

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int N=110,Mod=1000000007;
 6 int n,m,K,u[N],r[N];
 7 typedef long long LL;
 8 LL fac[N],ifac[N],c[N][N],f[N],g[N];
 9 LL Inv(LL x){return x==1?1:(Mod-Mod/x)*Inv(Mod%x)%Mod;}
10 LL C(int x,int y){
11     if(x<y||x<0||y<0)return 0;
12     return fac[x]*ifac[y]%Mod*ifac[x-y]%Mod;
13 }
14
15 LL Quick_pow(LL x,LL y){
16     LL ret=1;
17     while(y){
18         if(y&1)ret=ret*x%Mod;
19         y>>=1;x=x*x%Mod;
20     }
21     return ret;
22 }
23
24 int main(){
25     scanf("%d%d%d",&n,&m,&K);
26     for(int i=1;i<=m;i++)
27         scanf("%d",&u[i]);
28     for(int i=1;i<=m;i++)
29         scanf("%d",&r[i]);
30     fac[0]=ifac[0]=1;
31     for(int i=1;i<N;i++){
32         fac[i]=fac[i-1]*i%Mod;
33         ifac[i]=Inv(fac[i]);
34     }
35     for(int i=n-1;i>=K;i--){
36         f[i]=C(n-1,i);
37         for(int j=1;j<=m;j++)
38             (f[i]*=C(n-i-1,r[j]-1))%=Mod;
39         for(int j=i+1;j<n;j++){
40             (f[i]-=f[j]*C(j,i))%=Mod;
41             (f[i]+=Mod)%=Mod;
42         }
43     }
44     LL ans=f[K];
45     for(int i=1;i<=m;i++){
46         LL R=r[i],U=u[i];
47         g[0]=U;
48         for(int k=1;k<=n;k++){
49             g[k]=Quick_pow(U+1,k+1)-1;
50             for(int j=k-1;j>=0;j--)
51                 (g[k]+=Mod-C(k+1,j)*g[j]%Mod)%=Mod;
52             (g[k]*=Inv(C(k+1,k)))%=Mod;
53         }
54         LL tmp=0,rmp;
55         for(int j=1,s=1;j<=R;s*=-1,j++){
56             rmp=(s+Mod)*C(R-1,j-1)%Mod;
57             (rmp*=Quick_pow(U,R-j))%=Mod;
58             (rmp*=g[n-R+j-1])%=Mod;
59             (tmp+=rmp)%=Mod;
60         }
61         ans=ans*tmp%Mod;
62     }
63     printf("%lld\n",ans);
64     return 0;
65 }

  

  

时间: 2024-10-13 23:26:01

动态规划(计数DP):JLOI 2016 成绩比较的相关文章

【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

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

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

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

POJ 3071 Football (动态规划-概率DP)

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2768   Accepted: 1412 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all teams still in the

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]转