1. 程式人生 > 其它 >21.6.13 t1

21.6.13 t1

tag:揹包dp,插值


考場50分,對著資料懷疑人生一個小時,然後教練過來說資料掛了。。

然而下發的標程也掛了,又懷疑人生了一個小時。。

對於 \(40%\) 很容易就能想到列舉 \(m\),然後跑揹包dp。

仔細觀察這個dp是形如:

\[\sum_{S\subseteq\{1\cdots n\},|S|\ge k}(\prod_{i\not\in S}(a_im+b_i)\prod_{i\in S}(c_im+d_i)) \]

所以答案一定是關於 \(m\) 的多項式。

然後插值。


#include<bits/stdc++.h>
using namespace std;
 
template<typename T>
inline void Read(T &n){
    char ch; bool flag=false;
    while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
    for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
    if(flag)n=-n;
}
 
#define int long long
typedef long long ll;
enum{
    MAXN = 55,
    MOD = 1000000007,
};
int B;
 
inline int ksm(int base, int k=MOD-2){
    int res=1;
    while(k){
        if(k&1)
            res = 1ll*res*base%MOD;
        base = 1ll*base*base%MOD;
        k >>= 1;
    }
    return res;
}
 
inline int inc(int a, int b){
    assert(0<=a and a<MOD and 0<=b and b<MOD);
    a += b;
    if(a>=MOD) a -= MOD;
    return a;
}
 
inline int dec(int a, int b){
    assert(0<=a and a<MOD and 0<=b and b<MOD);
    a -= b;
    if(a<0) a += MOD;
    return a;
}
 
inline void ddec(int &a ,int b){a = dec(a,b);}
inline void iinc(int &a, int b){a = inc(a,b);}
inline void upd(int &a, ll b){a = (a+b)%MOD;}
 
int n, m, A, k;
int x[MAXN], y[MAXN], d[MAXN], f[MAXN][MAXN];
 
namespace ChaZhi{
    int x[MAXN<<1], y[MAXN<<1], mul[MAXN<<1], f[MAXN<<1], tmp[MAXN<<1];
    inline void Interpolate(int n){
        memset(mul,0,sizeof mul);
        memset(f,0,sizeof f);
        mul[0]=1;
        for(register int i=1; i<=n; i++){
            for(register int j=i; j; j--)
                mul[j] = dec(mul[j-1],1ll*mul[j]*x[i]%MOD);
            mul[0] = dec(0,1ll*mul[0]*x[i]%MOD);
        }
        for(register int i=1; i<=n; i++){
            ll S=1;
            for(register int j=1; j<=n; j++) if(i!=j) S = 1ll*S*dec(x[i],x[j])%MOD;
            S = 1ll*ksm(S)*y[i]%MOD;
            for(register int j=0; j<=n; j++) tmp[j]=mul[j];
            for(register int j=n; j; j--)
                upd(tmp[j-1],1ll*tmp[j]*x[i]),
                upd(f[j-1],1ll*tmp[j]*S);
        }
    }
 
    inline int Calc(int n, int k){
        int ans=0;
        for(register int i=n-1; i>=0; i--)
            ans=(1ll*ans*k+f[i])%MOD;
        return ans;
    }
}
using ChaZhi::Calc;
using ChaZhi::Interpolate;
 
int timepoint[MAXN*2], cnt;
int tmp[MAXN<<1];
 
signed main(){
    freopen("1.in","r",stdin);
    // freopen("11.out","w",stdout);
    Read(n); Read(m); Read(k); Read(A); B = n;
    for(register int i=1; i<=n; i++){
        Read(d[i]), Read(x[i]), Read(y[i]), d[i] = max(1ll,A-d[i]);
        timepoint[++cnt] = (x[i]+d[i]-1)/d[i];
        timepoint[++cnt] = y[i]/d[i]+1;
    }
    timepoint[++cnt] = m+1; timepoint[++cnt] = 1;
    sort(timepoint+1,timepoint+cnt+1);
    int sum=0;
    for(register int i=1; i<=cnt and timepoint[i]<=m; i++){
        int dlt=0;
        for(register int t=timepoint[i]; t<timepoint[i+1] and dlt<B; t++){
            dlt++; int ans=0;
            memset(f,0,sizeof f);
            f[0][0] = 1;
            for(register int j=1; j<=n; j++){
                ll lim = 1ll*d[j]*t;
                if(lim<x[j]) for(register int p=0; p<j; p++) f[j][p] = 1ll*(y[j]-x[j]+1)*f[j-1][p]%MOD;
                else if(lim>=y[j]) for(register int p=0; p<j; p++) f[j][p+1] = 1ll*(y[j]-x[j]+1)*f[j-1][p]%MOD;
                else for(register int p=0; p<j; p++)
                    upd(f[j][p],1ll*(y[j]-lim)*f[j-1][p]),
                    upd(f[j][p+1],1ll*(lim-x[j]+1)*f[j-1][p]);
            }
            for(register int j=k; j<=n; j++) iinc(ans,f[n][j]);
            ChaZhi::x[dlt] = t;
            ChaZhi::y[dlt] = ans;
        }
        if(dlt<B) for(register int j=1; j<=dlt; j++) iinc(sum,ChaZhi::y[dlt]);
        else{
            Interpolate(dlt);
            for(register int j=1; j<=dlt+1; j++) tmp[j] = Calc(dlt,j), iinc(tmp[j],tmp[j-1]);
            dlt++;
            for(register int j=1; j<=dlt; j++) ChaZhi::x[j] = j, ChaZhi::y[j] = tmp[j];
            Interpolate(dlt);
            iinc(sum,Calc(dlt,timepoint[i+1]-1));
            ddec(sum,Calc(dlt,timepoint[i]-1));
        }
    }
    cout<<sum<<'\n';
    return 0;
}