题解:P12251 [科大国创杯初中组 2025] 抽卡
有
思考确定序列后如何求解。考虑先手能选什么,容易发现条件为前
直接拉过来做也太倒闭了,肯定要拆贡献,容易拆成
接下来肯定是插值,就是 dp 里面每个值都是关于
发现一个前缀中
对于每段插值求函数的区间和即可,时间复杂度
:::success[点击查看参考代码]
#include<bits/stdc++.h>
#define TIME chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()
#define rep(i,l,r) for(int qwp=(r),i=(l);i<=qwp;i++)
#define per(i,r,l) for(int qwp=(l),i=(r);i>=qwp;i--)
using namespace std;
namespace c0dE1ng{
constexpr int mod=1e9+7;
constexpr int N=505;
inline void inc(int &x,const int y){x+=y,x-=x>=mod?mod:0;}
inline void dec(int &x,const int y){x-=y,x+=x<0?mod:0;}
inline int ksm(int a,int b,const int p){a%=p;int r=1;while(b){if(b&1)r=r*1ll*a%p;a=a*1ll*a%p,b>>=1;}return r%p;}
inline int inv(const int x){return ksm(x,mod-2,mod);}
int n,m,a[N],f[N][N],F[N][N],y[N];
inline int Lag(int x){
int res=0;rep(i,1,n+2){
int p=1,q=1;rep(j,1,n+2)if(i!=j)p=p*1ll*(x-j+mod)%mod,q=q*1ll*(i-j+mod)%mod;
inc(res,p*1ll*inv(q)%mod*y[i]%mod);
}return res;
}
void main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n>>m;rep(i,1,n)cin>>a[i],a[i]+=a[i-1];
rep(x,1,n+2){
rep(i,0,n)rep(j,0,n)f[i][j]=0;rep(j,0,n)f[n][j]=j;
per(i,n,1){
const int p=(a[i]-x+mod+1)*1ll*inv(a[i])%mod;
rep(j,0,n)inc(f[i-1][j],f[i][min(j+2,i)]*1ll*p%mod);
rep(j,0,n)inc(f[i-1][j],f[i][j]*1ll*(1+mod-p)%mod);
}rep(i,0,n)F[x][i]=f[i][0];
}
int ans=0;rep(i,1,n){
rep(x,1,n+2)y[x]=F[x][i-1],inc(y[x],y[x-1]);
inc(ans,Lag(a[i])),dec(ans,Lag(a[i-1]));
}
cout<<ans<<'\n';
}
}
int main(){
auto _Tbe=TIME;
c0dE1ng::main();
auto _Ted=TIME;
cerr<<"\nTIME:"<<_Ted-_Tbe<<"ms\n";
return 0;
}
/*
ulimit -s 1048576
g++ -O2 -std=c++14 -static A.cpp -o %;size %;./% < A.in > A.out
*/
:::