专栏文章
题解:P12251 [科大国创杯初中组 2025] 抽卡【暂无数据】
P12251题解参与者 15已保存评论 17
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 17 条
- 当前快照
- 1 份
- 快照标识符
- @mipjrdy5
- 此快照首次捕获于
- 2025/12/03 13:08 3 个月前
- 此快照最后确认于
- 2025/12/03 13:08 3 个月前
先分析一下如果牌堆确定了应该怎么做最优:
倒着处理牌堆,每次将两张卡牌的价值加入堆中并再弹出堆中最大值, 次之后牌取完,所有牌的值之和减堆中剩的 个数之和就是答案。
分 做法
先分析一下 分 怎么写:
所有牌的值之和很好求。
对于一种方案堆中剩的所有值之和我们考虑拆贡献:
指的是堆中剩的 个值。
所以我们考虑枚举 ,求:
此时只分两种权值 ,即 。
设 ,若当前枚举的数为 ,则第 次随机选择的卡牌值为 的方案数为 ,为 的方案数为 。
我们从后往前 dp, 表示处理好了第 到 次选择堆中有个 数值为 。
转移即:
至此 分结束。
分
比较明显 数组维护的是一个关于 的多项式,因为 递增我们可以发现对于 的所有 维护的多项式系数相同。
现在如果我们得到了 的系数,并且 。那么 。
所以 。
因此从后往前暴力算 的系数,然后就可以统计 的所有 的答案。
设 为 第 项的系数。
即:
最后我们用斯特林数或拉插求自然数幂和即可。
斯特林数求法:
数据出来再放代码。
CPP#include<bits/stdc++.h>
using namespace std;
const int N=505,mod=1e9+7;
#define vr vector<int>
int n,m,a[N],s=1,ans,sss,mi[N],inv[N],st[N][N],ss[N][N];vr f[N][N];
inline int pw(int x,int y) {
int z=1;
for(;y;y>>=1,x=x*1ll*x%mod) if(y&1) z=z*1ll*x%mod;
return z;
}
inline void ad(int &u,int v) {u+=v;(u>=mod&&(u-=mod));}
inline vr add2(vr x,vr y) {
vr z(max(x.size(),y.size()),0);
for(int i=0;i<x.size();++i) ad(z[i],x[i]);
for(int i=0;i<y.size();++i) ad(z[i],y[i]);
return z;
}
inline vr mul(vr x,vr y) {
vr z(x.size()+y.size()-1,0);
for(int i=0;i<x.size();++i) for(int j=0;j<y.size();++j) ad(z[i+j],x[i]*1ll*y[j]%mod);
return z;
}
inline int calc(int x) {return x*1ll*(x+1)/2ll%mod;}
vr tp;
inline vr make(int x,int y) {vr().swap(tp);tp.emplace_back(y);tp.emplace_back(x);return tp;}
inline vr make2(int x) {vr().swap(tp);tp.emplace_back(x);return tp;}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",a+i),a[i]+=a[i-1],s=s*1ll*a[i]%mod;sss=s;
for(int i=1;i*2<=n;++i) swap(a[i],a[n+1-i]);
for(int i=1;i<=n;++i) ans=(ans+calc(a[i])*1ll*s%mod*pw(a[i],mod-2))%mod;
st[0][0]=1;ans=ans*2%mod;
for(int i=1;i<=n;++i) for(int j=1;j<=i;++j) st[i][j]=(j*1ll*st[i-1][j]+st[i-1][j-1])%mod;
for(int i=1;i<=n+2;++i) inv[i]=pw(i,mod-2);
for(int i=1;i<=n;++i) {
mi[0]=1;
for(int j=1;j<=n+1;++j) mi[j]=mi[j-1]*1ll*(a[i]+2-j)%mod;
for(int j=0;j<=n;++j) for(int k=0;k<=j;++k) ss[i][j]=(ss[i][j]+st[j][k]*1ll*inv[k+1]%mod*mi[k+1])%mod;
}
f[0][0].emplace_back(1);ss[n+1][0]=1;
for(int i=1;i<=n;++i) {
for(int j=0;j<i;++j) {
f[i][j+1]=add2(f[i][j+1],mul(make(mod-1,a[i]+1),f[i-1][j]));
f[i][max(j-1,0)]=add2(f[i][max(j-1,0)],mul(make(1,mod-1),f[i-1][j]));
}
vr g;g.clear();
for(int j=n-i+1;j<=n;++j) g=add2(g,mul(make2(j-n+i),f[i][j]));
s=s*1ll*pw(a[i],mod-2)%mod;
for(int j=0;j<(int)g.size();++j) ans=(ans-g[j]*1ll*s%mod*(ss[i][j]-ss[i+1][j]))%mod;
}
if(ans<0) ans+=mod;ans=ans*1ll*pw(sss,mod-2)%mod;
printf("%d\n",ans);
return 0;
}
相关推荐
评论
共 17 条评论,欢迎与作者交流。
正在加载评论...