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;
}