4559: [JLoi2016]成绩比较

4559: [JLoi2016]成绩比较

Time Limit: 20 Sec   Memory Limit: 256 MB
Submit: 153   Solved: 100
[ Submit][ Status][ Discuss]

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

HINT

Source

[ Submit][ Status][ Discuss]



#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
 
const int N = 105;
typedef long long LL;
const LL mo = 1000000007;
 
int n,m,k,Max[N],Rank[N],C[N][N],f[N][N],g[N];
 
inline int Mul(const LL &x,const LL &y) {return x * y % mo;}
inline int Add(const int &x,const int &y) {return x + y < mo ? x + y : x + y - mo;}
inline int Dec(const int &x,const int &y) {return x - y >= 0 ? x - y : x - y + mo;}
 
inline int ksm(int x,int y)
{
    int ret = 1;
    for (; y; y >>= 1)
    {
        if (y & 1) ret = Mul(ret,x);
        x = Mul(x,x);
    }
    return ret;
}
 
inline int Calc(int U,int R)
{
    memset(g,0,sizeof(g));
    for (int i = 1; i < N; i++)
        for (int j = 1; j <= i; j++)
            g[i] = Add(g[i],Mul(ksm(j,n - R),ksm(i - j,R - 1)));
    int ret = 0;
    for (int i = 1; i < N; i++)
    {
        int A = g[i],B = 1;
        for (int j = 1; j < N; j++)
        {
            if (i == j) continue;
            A = Mul(A,Dec(U,j)); B = Mul(B,Dec(i,j));
        }
        ret = Add(ret,Mul(A,ksm(B,mo - 2)));
    }
    return ret;
}
 
int main()
{
    #ifdef DMC
        freopen("DMC.txt","r",stdin);
    #endif
     
    cin >> n >> m >> k; C[0][0] = f[0][n - 1] = 1;
    for (int i = 1; i <= n; i++)
    {
        C[i][0] = 1;
        for (int j = 1; j <= i; j++)
            C[i][j] = Add(C[i - 1][j],C[i - 1][j - 1]);
    }
    for (int i = 1; i <= m; i++) scanf("%d",&Max[i]);
    for (int i = 1; i <= m; i++) scanf("%d",&Rank[i]);
    for (int i = 1; i <= m; i++)
    {
        int h = Calc(Max[i],Rank[i]);
        for (int j = k; j <= n - 1; j++)
            for (int t = j; t <= n - 1; t++)
            {
                if (t - j > Rank[i] - 1) break;
                int now = Mul(C[t][t - j],C[n - 1 - t][Rank[i] - 1 - t + j]);
                f[i][j] = Add(f[i][j],Mul(now,Mul(f[i - 1][t],h)));
            }
    }
    cout << f[m][k] << endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值