zoukankan      html  css  js  c++  java
  • bzoj4559[JLoi2016]成绩比较 容斥+拉格朗日插值法

    4559: [JLoi2016]成绩比较

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 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神的说法中,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

    容斥+拉格朗日插值法

    讲一个性质:

    对于n阶等差数列 (如 1^5,2^5,3^5,4^5….被称为5阶等差)

    它们的前n项和可以用一个最高次为n+1次的多项式表示

    它们的通项公式可以用一个最高次为n次的多项式表示

    因此,我们可以用拉格朗日插值法来优化一些多项式计算

     


    (其实我不是很懂)
    推荐blog
    http://www.cnblogs.com/zj75211/p/8029303.html

    #include<cstdio> 
    #include<cstring>
    #include<iostream>
    #define MAXN 105
    #define _ %mod
    #define filein(x) freopen(#x".in","r",stdin);
    #define fileout(x) freopen(#x".out","w",stdout);
    using namespace std;
    const int mod=1000000007;
    int dp[MAXN],U[MAXN],R[MAXN],C[MAXN][MAXN],Y[MAXN],inv[MAXN];
    int N,M,K,ANS;
    int pow(int a,int b){
        int now=1;
        while(b){
            if(b&1) now=(1ll*now*a)_;
            a=(1ll*a*a)_; b>>=1;
        }
        return now;
    }
    int Lagrange(int u,int r){
        static int lpi[MAXN],rpi[MAXN],p[MAXN],ans,tmp;
        lpi[0]=1; rpi[N+2]=1; ans=0;
        for(int i=1;i<=N+1;i++){
            p[i]=(1ll*p[i-1]+1ll*pow(i,N-r)*pow(u-i,r-1)_)_;
            if(i==u) return p[i];
        }
        for(int i=1;i<=N+1;i++) lpi[i]=1ll*lpi[i-1]*(u-i)_;
        for(int i=N+1;i>=1;i--) rpi[i]=1ll*rpi[i+1]*(u-i)_;
        for(int i=1;tmp=1,i<=N+1;i++){
            tmp=1ll*tmp*lpi[i-1]_*rpi[i+1]_*inv[i-1]_*inv[N+1-i]_*p[i]_;
            tmp=(1ll*tmp*((N+1-i)&1?-1:1)+mod)_;
            ans=(1ll*ans+tmp)_;
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d%d",&N,&M,&K);
        inv[0]=1; inv[1]=1; 
        for(int i=2;i<=N+1;i++) inv[i]=((-1ll*(mod/i)*inv[mod%i])_+mod)_;
        for(int i=1;i<=N+1;i++) inv[i]=1ll*inv[i]*inv[i-1]_;
        for(int i=1;i<=M;i++) scanf("%d",&U[i]);
        for(int i=1;i<=M;i++) scanf("%d",&R[i]);
        for(int i=0;i<=N;i++){
            C[i][0]=1;
            for(int j=1;j<=i;j++)
                C[i][j]=(1ll*C[i-1][j-1]+C[i-1][j])_;
        }
        for(int i=1;i<=M;i++) Y[i]=Lagrange(U[i],R[i]);
        for(int i=N-1;i>=K;i--)
        {
            dp[i]=C[N-1][i];
            for(int j=1;j<=M;j++)    dp[i]=1ll*dp[i]*C[N-i-1][N-R[j]-i]_;
            ANS=(1ll*ANS+(((i^K)&1)?-1:1)*1ll*dp[i]*C[i][K]_+mod)_;
        }
        for(int i=1;i<=M;i++) ANS=1ll*ANS*Y[i]_;
        printf("%d",(ANS+mod)_);
        return 0;
    }
  • 相关阅读:
    第十三周总结
    第一阶段意见评论
    第十二周总结
    关于transform的3D变形函数
    12.9学习内容
    12.8学习的内容
    这是自己的第一篇博客
    食物链
    poj1988Cute Stacking
    银河英雄传说
  • 原文地址:https://www.cnblogs.com/wsy01/p/8031918.html
Copyright © 2011-2022 走看看