Portal -->bzoj4559

补档计划

​   借这题补个档——拉格朗日插值

​​   插值的话大概就是有一个\(n-1\)次多项式\(A(x)\),你只知道它在\(n\)处的点值,分别是\((x_1,y_1),(x_2,y_2),...,(x_{n},y_{n})\),让你还原这个多项式

​   关于插值我们有很多的方法,有十分粗暴的高消\(O(n^3)\),也有十分优秀的快速差值(不会qwq),还有拉格朗日插值法\(O(n^2)\)(emmm如果说取值位置连续的话。。可以做到\(O(n)\))

​​   其实拉格朗日差值的核心就是这两条式子:

\[\begin{aligned}
l_j(x)&=\sum\limits_{i=0,i\neq j}^n\frac{x-x_i}{x_j-x_i}\\
A(x)&=\sum\limits_{i=1}^{n}y_i\cdot l_i(x)
\end{aligned}
\]

​​   具体为什么的话就是,首先有\(n\)个处点值是可以确定一个\(n-1\)次多项式,并且这个多项式是惟一的,那么接下来就是看为什么这样构造是满足条件的:我们观察\(l_j(x)\)这个多项式的值,当代进去的值为\(x_i\)中的其中一个时,这个多项式才会为\(1\),否则为\(0\),所以乘上一个\(y_i\)然后求一下和就可以满足这\(n\)处的取值了

​​   然后就是这个东西怎么比较。。快一点的求

​   大概是。。我们可以先求出\(C(x)=\sum\limits_{i=1}^n(x-x_i)\)这个多项式各项系数(可以在\(O(n)\)的时间内得到,具体的话就是考虑每次暴力拆括号然后未知数的幂指数\(+1\),然后系数要乘上\(-x_i\)),求出这个东西之后,我们就可以在\(O(n)\)的时间内求出\(B_j(x)=\sum\limits_{i=1,i\neq j}^n(x-x_i)\)(具体就是直接考虑将\((x-x_j)\)这项的贡献去掉就好了),然后我们又可以用\(B_j(x)\)求出分母然后其他的随便乱搞都可以了

​   那为什么说取值位置连续的话可以\(O(n)\)呢?其实。。因为是连续的所以我们的分子可以用阶乘什么的乱搞,然后分母维护一个前缀乘积,一个后缀乘积就好了(实际上好像前缀成绩后缀乘积这个东西完全可以在非连续情况下使用但是反正分母那里要\(O(n)\)又何必搞那么麻烦呢嘿嘿。。。)

​​   这里贴一下非连续取值的时候的代码(虽然说这题根本不用不过反正都是补档嘛。。一起写好了)

void solve(int n){
memset(c,0,sizeof(c));
c[0]=1;
for (int i=1;i<=n;++i){
for (int j=n;j>=0;--j){
c[j+1]=(c[j+1]+c[j])%MOD;
c[j]=(-c[j]*X[i])%MOD;
}
}//get 系数 of \prod_{i=0}^k (x-x_i)
ll s=0,tmp=1;
for (int i=1;i<=n;++i){
memcpy(d,c,sizeof(d));
memset(b,0,sizeof(b));
for (int j=n;j>=0;--j){
b[j]=d[j+1];
d[j]=(d[j]+d[j+1]*X[i])%MOD;
d[j+1]=0;
}//take (x-x_i) out of \prod_{j=0}^k (x-x_j)
s=0,tmp=1;
for (int j=0;j<=n;++j){
s=(s+tmp*b[j])%MOD;
tmp=tmp*X[i]%MOD;
}//get \prod_{j=0,j!=i}^k (x_i-x_j) s=ksm(s,MOD-2)*Y[i]%MOD;
for (int j=0;j<=n;++j) b[j]=b[j]*s%MOD;//get the final 系数
for (int j=0;j<=n;++j)
ans[j]=(ans[j]+b[j])%MOD;
}
}

​  

Solution

​​   然后我们来看这题

​​   这题的做法很多。。网上有十分优秀的根本不需要拉格朗日插值的做法。。但是我比较菜所以。。

​​   考虑一下这个答案要怎么算,因为题目的限制条件有点多所以我们考虑将它拆成两个部分来想:

1.先不管具体分数是多少,只考虑相对大小,求出满足有恰好\(K\)个人各门分数都小于等于\(B\)神的方案数,记为\(ans1\)

2.算具体分数是多少

​​   那么最后的答案就应该是\(ans1\)再乘上对应的第二部分中具体分数不同的贡献

​​   我们先来考虑第一部分,这里。。我们考虑用dp+容斥来求解(注意,接下来的dp中所有的转移都不考虑每个人的具体得分,我们在第一部分的求解中只考虑相对大小)

​​   记\(f[i]\)表示至少\(i\)个人满足条件的方案数,那么我们可以得到:

\[f[i]=\binom{n-1}i \prod\limits_{j=1}^m \binom{n-1-i}{R_j-1}
\]

​​   其中\(R_j\)表示的是\(B\)神在第\(j\)门科目中的排名,这个式子具体一点的含义的话就是:首先我们需要钦定\(i\)个人是满足条件的,所以总共是\(\binom {n-1}i\)中选法,然后在钦定了\(i\)个人一定排在\(B\)神之后的前提下,我们对于每一门科目又要满足有\(R_j-1\)个人分数大于\(B\)神,那只能从\(n-1-i\)个人中选,所以就是后面的按个组合数了

​   有了这个东西之后我们构造一下容斥系数\(a(i)\):

\[ans1=\sum\limits_{i=K}^na(i)f[i]
\]

​​   其实仔细想一下就可以得出:

\[ans1=\sum\limits_{i=K}^n(-1)^{K-i}\binom i Kf[i]
\]

​​   具体一点就是你考虑\(f[i]\)的含义就是至少\(i\)个人满足条件,那么这个\(K\)个人中一旦有\(i\)个人是被钦定的,\(f[i]\)就会被算一次,所以乘个系数就好了

​  

​​   然后第一部分我们就算完了

​​   接着是第二部分(这部分才到插值==)

​​   第二部分的话,我们要考虑每个人具体是什么分数了,我们要求的东西其实就是要求有\(x\)个人比\(B\)神低,\(y\)个人比\(B\)神高的分数有多少种(与第一部分不同的是,这里不需要考虑具体是哪一个人,而是考虑分数)

​​   那么对于一门科目\(i\),我们有\(y=R_i-1,x=(n-1)-y\), 所以我们只要枚举一下\(B\)神的分数就好了:

\[\sum\limits_{j=1}^{U_i}(U_i-j)^{R_i-1}\cdot j^{(n-1)-(R_i-1)}
\]

​​   其中\(U_i\)表示这门科目分数上限

​​   那么所有的科目的总贡献就是:

\[ans2=\prod\limits_{i=1}^m\sum\limits_{j=1}^{U_i}(U_i-j)^{R_i-1}\cdot j^{(n-1)-(R_i-1)}
\]

​​   最终答案就是\(ans1*ans2\)啦

​​   但是我们看\(U_i\)的范围是\(10^9\),所以。。不能直接算,又发现如果说我们将\(U_i\)看成一个变量的话,每门科目的贡献可以看成一个\(n\)次多项式\(P(x)\)(次数最高只能到\(n\)),那所以我们可以先暴力带入\(x=0...n\),然后把这\(n+1\)个点值算出来,然后每次\(O(n^2)\)求值就好了(具体的话就是直接代进拉格朗日插值的那条式子)

​​   总的时间复杂度\(O(n^3)\)(其实。。求值好像可以做到每次\(O(n)\)的。。不过\(n=100\)我就写了最暴力的这种了qwq)

​ ​  

​   代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=110,MOD=1e9+7;
int u[N],r[N],f[N],c[N][N],g[N];
int n,m,K,ans1,ans2;
int add(int x,int y){return (1LL*x+y)%MOD;}
int mul(int x,int y){return 1LL*x*y%MOD;}
void predp(){
c[0][0]=1;
for (int i=1;i<=n;++i){
c[i][0]=1; c[i][i]=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<=n;++i){
f[i]=c[n-1][i];
for (int j=1;j<=m;++j)
f[i]=mul(f[i],c[n-1-i][r[j]-1]);
}
}
int ksm(int x,int y){
int ret=1,base=x;
for (;y;y>>=1,base=mul(base,base))
if (y&1) ret=mul(ret,base);
return ret;
}
void precalc(int U,int R,int &val){
int tmp;
val=0;
for (int i=1;i<=U;++i){
tmp=mul(ksm(U-i,R-1),ksm(i,(n-1)-(R-1)));
val=add(val,tmp);
}
}
int calc(int x){
int fz,fm,ret=0;
for (int i=0;i<=n;++i){
fz=1; fm=1;
for (int j=0;j<=n;++j){
if (j==i) continue;
fz=mul(fz,(x-j+MOD)%MOD);
fm=mul(fm,(i-j+MOD)%MOD);
}
ret=add(ret,1LL*fz*ksm(fm,MOD-2)%MOD*g[i]%MOD);
}
return ret;
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&K);
for (int i=1;i<=m;++i) scanf("%d",u+i);
for (int i=1;i<=m;++i) scanf("%d",r+i);
predp();
ans1=0;
for (int i=K;i<=n;++i){
if ((K-i)%2==0)
ans1=add(ans1,mul(c[i][K],f[i]));
else
ans1=add(ans1,(1LL*MOD-mul(c[i][K],f[i]))%MOD);
}
ans2=1;
for (int i=1;i<=m;++i){
if (i==6)
int debug=1;
for (int j=0;j<=n;++j)
precalc(j,r[i],g[j]);
ans2=mul(ans2,calc(u[i]));
}
printf("%d\n",mul(ans1,ans2));
}

【bzoj4559】成绩比较的更多相关文章

  1. BZOJ4559 成绩比较

    题目传送门 分析: 我们可以先试着求一下,对于单个学科,有多少种分配方案可以使B神排名为R 对于第i个学科 \(~~~~g(i)=\sum_{j=1}^{H_i}j^{n-R_i}(H_i-j)^{R ...

  2. 【BZOJ4559】成绩比较(动态规划,拉格朗日插值)

    [BZOJ4559]成绩比较(动态规划,拉格朗日插值) 题面 BZOJ 洛谷 题解 显然可以每门课顺次考虑, 设\(f[i][j]\)表示前\(i\)门课程\(zsy\)恰好碾压了\(j\)个\(yy ...

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

    [BZOJ4559][JLoi2016]成绩比较 Description G系共有n位同学,M门必修课.这N位同学的编号为0到N-1的整数,其中B神的编号为0号.这M门必修课编号为0到M-1的整数.一 ...

  4. 【BZOJ4559】成绩比较(组合计数,容斥原理)

    题意: G系共有n位同学,M门必修课.这N位同学的编号为0到N-1的整数,其中B神的编号为0号.这M门必修课编号为0到M- 1的整数.一位同学在必修课上可以获得的分数是1到Ui中的一个整数.如果在每门 ...

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

    4559: [JLoi2016]成绩比较 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 261  Solved: 165[Submit][Status ...

  6. BZOJ4559: [JLoi2016]成绩比较(dp 拉格朗日插值)

    题意 题目链接 Sol 想不到想不到.. 首先在不考虑每个人的真是成绩的情况下,设\(f[i][j]\)表示考虑了前\(i\)个人,有\(j\)个人被碾压的方案数 转移方程:\[f[i][j] = \ ...

  7. BZOJ4559 JLOI2016成绩比较(容斥原理+组合数学+斯特林数)

    容斥一发改为计算至少碾压k人的情况数量,这样对于每门课就可以分开考虑再相乘了.剩下的问题是给出某人的排名和分数的值域,求方案数.枚举出现了几种不同的分数,再枚举被给出的人的分数排第几,算一个类似斯特林 ...

  8. bzoj千题计划270:bzoj4559: [JLoi2016]成绩比较(拉格朗日插值)

    http://www.lydsy.com/JudgeOnline/problem.php?id=4559 f[i][j] 表示前i门课,有j个人没有被碾压的方案数 g[i] 表示第i门课,满足B神排名 ...

  9. 【bzoj4559】[JLoi2016]成绩比较(dp+拉格朗日插值)

    bzoj 题意: 有\(n\)位同学,\(m\)门课. 一位同学在第\(i\)门课上面获得的分数上限为\(u_i\). 定义同学\(A\)碾压同学\(B\)为每一课\(A\)同学的成绩都不低于\(B\ ...

随机推荐

  1. 内容安全策略(CSP)

    内容安全策略(CSP),其核心思想十分简单:网站通过发送一个 CSP 头部,来告诉浏览器什么是被授权执行的与什么是需要被禁止的.其被誉为专门为解决XSS攻击而生的神器. 1.CSP是什么 CSP指的是 ...

  2. 韦大仙--LoadRunner压力测试:详细操作流程

    一. 录制脚本 1.安装完毕后,创建脚本: 点击OK之后,会弹出网址,之后创建Action,每进一个页面添加一个Action,录制结束后,终止录制. 二. 修改脚本 1.脚本参数化 将登录的用户名密码 ...

  3. Spring Cloud(一):服务治理技术概览【Finchley 版】

    Spring Cloud(一):服务治理技术概览[Finchley 版]  发表于 2018-04-14 |  更新于 2018-05-07 |  Spring Cloud Netflix 是 Spr ...

  4. 2.1 Oracle之DML的SQL语句之单表查询以及函数

    1.SQL简介 对于不同的数据库来说,SQL语句是相通的,关系型数据库都以SQL语句为操作的标准,只是相应的数据库对应的函数不相同. SQL(Structured Query Language,结构化 ...

  5. Tensorflow框架之AlexNet

    from datetime import datetime import math import time import tensorflow as tf batch_size=32 num_batc ...

  6. 启动tomcat时 一闪而过解决方法(2)

    下面我先跟大家确认一下问题出现的前提条件(本机版本java:1.6.20,tomcat:6.0.32) 1)在eclipse里面启动tomcat时都是正常的. 2)在系统中配置了各种环境变量如下: J ...

  7. [shell] sed学习

    Q:匹配内容有1没有a的行 echo -e "1a\n2b\n1b\n2a" | sed -n '/1/{/a/d;p}' echo -e "1a\n2b\n1b\n2a ...

  8. linux 性能分析命令及其解释

    很多时候,我们需要对linux上运行的环境大体有一个了解,那么久需要大体知道当前系统的相关资源的使用情况,那么可以用一些linux提供的丰富的命令来查看 性能分析 vmstat 虚拟内存统计 用法 U ...

  9. winform default模式下和英文模式下 修改问题

    1.修改控件大小.位置等属性在default模式下修改: 2.修改控件属性最好不要做鼠标拖动放大,拖动修改位置等,建议用属性栏中的数字来改变.

  10. JNDI和JDBC

    没有JNDI的做法:程序员开发时,知道要开发访问MySQL数据库的应用,于是将一个对 MySQL JDBC 驱动程序类的引用进行了编码,并通过使用适当的 JDBC URL 连接到数据库.就像以下代码这 ...