bzoj4559 performance comparison [dynamic programming + Lagrange interpolation]

Posted by chaser7016 on Sat, 13 Jun 2020 19:17:36 +0200

Solving ideas:

Let's set f[i][j] to represent the number of programs i n the previous i-course where a total of J people were not crushed. The answer is f[m][n_1_k]

Assume the transfer from f[i_1][w] to f[i][j](j < w)
The number of people who were not crushed should have increased by Ri_1, but some may not have been crushed before.
There are t1=j_w individuals who are new. To select from n_1_w individuals, the number of options is Ct1n_1_w
There are also t2=Ri_1_t 1 people who were never crushed. To select from w individuals, the number of options is Ct2w
For example, w=100,Ri_1=5,j=102, then t1=2,t2=3

Consider the scoring scheme for Lesson i I. If God B gets an x-score, there will be Ri_1 people with a score greater than him and n_Ri with a personal score less than or equal to him, so the total number of scenarios is
g(i)=∑x=1Ui(Ui−x)r−1xn−r
Because Ui is so large that it cannot be calculated directly, but notice that it is a polynomial whose number of times about Ui is less than or equal to n, you can use Lagrange interpolation to interpolate U=1,2...N+1 takes n+1 points and calculates the value of g(i).
Because Ri is different, it is required for each course.

Here we get the total dp equation:

f[i][j]=g(i)∑w=0jCt1n−1−wCt2wf[i−1][w]

Time complexity is O(n3)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=105,p=1e9+7;
int n,m,k;
int U[N],R[N],c[N][N],f[N][N];
int g[N],inv[N];

int ksm(int x,int y)
{
    x%=p;int res=1;
    for(;y;y>>=1,x=1ll*x*x%p)
        if(y&1)res=1ll*res*x%p;
    return res;
}

int Inter(int u,int r)
{
    memset(g,0,sizeof(g));
    for(int x=1;x<=n+1;x++)
    {
        for(int i=1;i<=x;i++)
            g[x]=(g[x]+1ll*ksm(x-i,r-1)*ksm(i,n-r)%p)%p;
        if(u==x)return g[x];
    }
    for(int i=1;i<=n+1;i++)
    {
        inv[i]=1;
        for(int j=1;j<=n+1;j++)
            if(i!=j)inv[i]=(1ll*inv[i]*(i-j)%p+p)%p;
        inv[i]=ksm(inv[i],p-2);
    }
    int res=0;
    for(int i=1;i<=n+1;i++)
    {
        int tmp=1ll*inv[i]*g[i]%p;
        for(int j=1;j<=n+1;j++)
            if(i!=j)tmp=1ll*tmp*(u-j)%p;
        res=(res+tmp)%p;
    }
    return res;
}

int C(int i,int j)
{
    if(i<0||j<0||j>i)return 0;
    return c[i][j];
}

int main()
{
    //freopen("lx.in","r",stdin);
    //freopen("lx.out","w",stdout);
    n=getint(),m=getint(),k=getint();
    for(int i=1;i<=m;i++)U[i]=getint();
    for(int i=1;i<=m;i++)R[i]=getint();
    c[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=n;j++)
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%p;
    }
    f[0][0]=1;
    for(int i=1;i<=m;i++)
    {
        int tmp=Inter(U[i],R[i]);
        for(int j=0;j<=n;j++)
        {
            for(int w=0;w<=j;w++)
                f[i][j]=(f[i][j]+1ll*f[i-1][w]*C(n-1-w,j-w)%p*C(w,R[i]-1-(j-w))%p*tmp%p)%p;
        }
    }
    cout<<f[m][n-1-k]<<'\n';
    return 0;
}

Topics: less