bzoj4559 [JLOI2016]成绩比较 拉格朗日插值

题目描述

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神那么厉害,你只需要计算出情况数模10^9+7的余数就可以了。

输入格式:

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

第二行包含M个正整数,依次表示每门课的最高分Ui。

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

数据保证至少有1种情况使得B神说的话成立。

输出格式:

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



\(f[i][j]中i表示处理到第i个科目,j表示到第i个科目有j个人被B神碾压\)

\(转移条件为\)

\[
f[i][j]=\sum_{k=j}^{n-1}{f[i-1][k]*C_{k}^{k-j}*C_{n-1-k}^{rank[i]-1-k+j}*\sum_{p=1}^{U_i}p^{n-rank[i]}(U_i-p)^{rank[i]-1}}
\]

对公式的理解可以参考https://www.luogu.org/blog/winxp/solution-p3270

然后后面的\(g[i]=\sum_{p=1}^{U_i}p^{n-rank[i]}(U_i-p)^{rank[i]-1}\)就是关于\(U_i\)的\(n\)次式,利用拉格朗日插值法求值即可。

具体实现:记录每次\(rank[i]\)情况下的\(g[i] (i\in 1,2,...,n)\)的值,然后利用拉格朗日插值公式求解\(g[U_i]\)的值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=105;
const int mod=1e9+7;
int read(){
    int x=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)ff=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-‘0‘;ch=getchar();}
    return x*ff;
}
int C[N][N];
int f[N][N];
int g[N];
int n,m,K;
int mx[N],rnk[N];
void init(){
    C[0][0]=1;
    for(int i=1;i<N;i++){//千万不要等于N,爆数组就错了……调了半天qwq
        C[0][i]=1;
        for(int j=1;j<=i;j++)
            C[j][i]=1LL*(C[j-1][i-1]+C[j][i-1])%mod;
    }
}
int pow(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=1LL*res*a%mod;
        a=1LL*a*a%mod;
        b/=2;
    }
    return res;
}
int cal(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]=1LL*(g[i]+1LL*pow(j,n-R)*pow(i-j,R-1)%mod)%mod;
    int res=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=1LL*a*(U-j)%mod;
            a=(a+mod)%mod;//注意防止为负
            b=1LL*b*(i-j)%mod;
            b=(b+mod)%mod;
        }
        res=1LL*(res+1LL*a*pow(b,mod-2)%mod)%mod;
    }
    return res;
}
int main()
{
    // freopen("4559.in","r",stdin);
    // freopen("4559.out","w",stdout);
    n=read();m=read();K=read();
    init();
    f[0][n-1]=1;
    for(int i=1;i<=m;i++)mx[i]=read();
    for(int i=1;i<=m;i++)rnk[i]=read();
    for(int i=1;i<=m;i++){
        int d=cal(mx[i],rnk[i]);
        for(int j=K;j<=n-1;j++)
            for(int k=j;k<=n-1;k++){
                if(k-j>rnk[i]-1)continue;
                int tmp=1LL*C[k-j][k]*C[rnk[i]-1-k+j][n-1-k]%mod;
                f[i][j]=1LL*(f[i][j]+1LL*f[i-1][k]*tmp%mod*1LL*d%mod)%mod;
            }
    }
    printf("%d\n",f[m][K]);
    return 0;
}

原文地址:https://www.cnblogs.com/Nan-Cheng/p/9735234.html

时间: 2024-10-09 14:57:11

bzoj4559 [JLOI2016]成绩比较 拉格朗日插值的相关文章

bzoj千题计划270:bzoj4559: [JLoi2016]成绩比较

http://www.lydsy.com/JudgeOnline/problem.php?id=4559 f[i][j] 表示前i门课,有j个人没有被碾压的方案数 g[i] 表示第i门课,满足B神排名的分数安排方案数 g[i]的求法: 枚举B神这门课x分,则有n-Ri个人的分数<=x ,Ri-1个人的分数>x Ui 上限是1e9,但是g[i] 是一个关于Ui 的n次多项式,所以可以用拉格朗日插值法来求 递推 f[i][j]: 假设f[i-1][w] 转移到了f[i][j],j>=w 前i

bzoj4559: [JLoi2016]成绩比较

感谢丁爷爷教我做这个题的后半部分. 首先,运用一发容斥原理,求出所有人与B神每门课分数相对关系的不同方案数. 这个似乎大(wo)家(lan)都(de)会(hui)了(yi),我就不说了,详见代码里的f. 然后,我们就需要计算每门课每个人的分数的方案数.对于每一门课,我们分别计算,然后把它们乘起来. 方便起见,令总分为s,名次为rk. 设B神的分数为x,则方案数为x^(n-rk)*(s-x)^(rk-1) 展开得到c(rk-1,0)*s^(rk-1)*x^(n-rk)-c(rk-1,1)*s^(r

BZOJ4599[JLoi2016&amp;LNoi2016]成绩比较(dp+拉格朗日插值)

这个题我们首先可以dp,f[i][j]表示前i个科目恰好碾压了j个人的方案数,然后进行转移.我们先不考虑每个人的分数,先只关心和B的相对大小关系.我们设R[i]为第i科比B分数少的人数,则有f[i][j]=sum f[i-1][k]*C(k,j)*C(n-1-k,R[i]-j)  (k>=j) 怎么解释呢,首先前i-1科有k个人已经被碾压,k肯定大于等于j,然后考虑当前这一科有j个人被碾压,那么就需要从k个人中选出j个来即C(k,j),然后从剩下的有R[i]-j个人比B考的少,这些人必须是之前i

bzoj 4559 [JLoi2016]成绩比较 —— DP+拉格朗日插值

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4559 看了看拉格朗日插值:http://www.cnblogs.com/ECJTUACM-873284962/p/6833391.html https://blog.csdn.net/lvzelong2014/article/details/79159346 https://blog.csdn.net/qq_35649707/article/details/78018944 还只会最简单的

【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

【BZOJ4559】[JLoi2016]成绩比较 动态规划+容斥+组合数学

[BZOJ4559][JLoi2016]成绩比较 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,则表示有且

4559[JLoi2016]成绩比较 容斥+拉格朗日插值法

4559: [JLoi2016]成绩比较 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 261  Solved: 165[Submit][Status][Discuss] Description G系共有n位同学,M门必修课.这N位同学的编号为0到N-1的整数,其中B神的编号为0号.这M门必修课编号为0到M- 1的整数.一位同学在必修课上可以获得的分数是1到Ui中的一个整数.如果在每门课上A获得的成绩均小于等于B获 得的成绩,则称A被B碾压.在B

【LuoguP3270】[JLOI2016] 成绩比较

题目链接 题目描述 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神的分数,有且仅

[JLOI2016] 成绩比较

推石子 首先设\(d[i]=\sum_{t=1}^{U[i]}t^{n-R[i]}(U[i]-t)^{R[i]-1}\),即第\(i\)门课程分数的合法分布方案数: 然后设\(f[i,j]\)表示前\(i\)门课程中\(j\)个人被碾压的合法方案数,转移有: \[ \begin{aligned} &f[i,j]=d[i]\times\sum_{k=1}^n\pmatrix{k\\k-j}\pmatrix{n-k-1\\(R[i]-1)-(k-j)}f[i-1,k] &f[0,n-1]=1