题解 [LNOI2022] 盒
答案是
\[\sum\limits_{i=0}^{n-1}w_i\sum\limits_{j=0}^{s_i}|s_i-j|\binom{i+j-1}{j}\binom{n−i+S−j-1}{n-i-1}
\]
然后照着题解推式子
- \(j\binom{i+j-1}{j}=i\binom{i+j-1}{j-1}\),用于在求和式中将变量系数化为不变量系数提到外面
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 3000010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N];
const ll mod=998244353;
ll w[N], fac[N], inv[N];
namespace force{
bool vis[N];
ll dis[N], ans;
int b[N], inc[N], back[N], sum;
int head[N], ecnt, s, t, tot;
struct edge{int to, next, flw; ll cst;}e[N<<1];
inline void add(int s, int t, int f, ll c) {e[++ecnt]={t, head[s], f, c}; head[s]=ecnt;}
bool spfa(int s, int t) {
for (int i=1; i<=tot; ++i) dis[i]=INF, back[i]=-1;
queue<int> q;
dis[s]=0; inc[s]=INF;
q.push(s);
while (q.size()) {
int u=q.front(); q.pop();
vis[u]=0;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (e[i].flw && dis[v]>dis[u]+e[i].cst) {
dis[v]=dis[u]+e[i].cst;
back[v]=i; inc[v]=min(inc[u], e[i].flw);
if (!vis[v]) vis[v]=1, q.push(v);
}
}
}
return ~back[t];
}
void calc() {
ecnt=1; tot=n+2;
for (int i=1; i<=n+2; ++i) head[i]=-1;
s=n+1; t=n+2;
for (int i=1; i<=n; ++i) add(s, i, a[i], 0), add(i, s, 0, 0);
for (int i=1; i<=n; ++i) add(i, t, b[i], 0), add(t, i, 0, 0);
for (int i=2; i<=n; ++i) add(i, i-1, INF, w[i-1]), add(i-1, i, 0, -w[i-1]);
for (int i=1; i<n; ++i) add(i, i+1, INF, w[i]), add(i+1, i, 0, -w[i]);
ll ans=0;
int tem=0;
while (spfa(s, t)) {
tem+=inc[t];
ans=(ans+inc[t]*dis[t])%mod;
for (int u=t; u!=s; u=e[back[u]^1].to) {
e[back[u]].flw-=inc[t];
e[back[u]^1].flw+=inc[t];
}
}
// cout<<tem<<endl;
force::ans=(force::ans+ans)%mod;
}
void dfs(int u, int rest) {
if (u>n) {if (!rest) calc(); return ;}
for (int i=0; i<=rest; ++i) b[u]=i, dfs(u+1, rest-i);
}
void solve() {
ans=sum=0;
for (int i=1; i<=n; ++i) sum+=a[i];
dfs(1, sum);
printf("%lld\n", ans);
}
}
namespace task{
ll ans;
int sum[N], lim;
inline ll C(int n, int k) {return n<k?0:fac[n]*inv[k]%mod*inv[n-k]%mod;}
struct func{
ll val;
int n, m, p, q;
void init(int a, int b) {n=a; m=b; p=q=0; val=C(n+m-1, m);}
void upd(int x, int y) {
while (p<x) ++p, val=(val-C(p+q, q)*C(n-p+m-q-1, n-p))%mod;
while (q<y) ++q, val=(val+C(p+q, q)*C(n-p+m-q-1, m-q))%mod;
}
}f1, f2;
ll qval(int n, int m, int p, int q) {
ll ans=0;
for (int i=0; i<=q; ++i) ans=(ans+C(p+i, p)*C(n-p+m-i-1, m-i))%mod;
return ans;
}
void solve() {
for (int i=1; i<=n; ++i) sum[i]=sum[i-1]+a[i];
lim=n+sum[n]; ans=0;
f1.init(n-1, sum[n]); f2.init(n, sum[n]-1);
for (int i=1; i<n; ++i) {
ll tem=0;
// for (int j=0; j<=sum[i]; ++j) tem=(tem+2ll*sum[i]*C(i+j-1, j)%mod*C(n-i+sum[n]-j-1, sum[n]-j))%mod;
// tem=(tem+2ll*sum[i]*qval(n-1, sum[n], i-1, sum[i]))%mod;
f1.upd(i-1, sum[i]), tem=(tem+2ll*sum[i]*f1.val)%mod;
// for (int j=0; j<=sum[i]-1; ++j) tem=(tem-2ll*i*C(i+j, j)%mod*C(n-i+sum[n]-j-2, sum[n]-j-1))%mod;
// tem=(tem-2ll*i*qval(n, sum[n]-1, i, sum[i]-1))%mod;
if (sum[i]) f2.upd(i, sum[i]-1), tem=(tem-2ll*i*f2.val)%mod;
tem=(tem+i*C(n+sum[n]-1, n)-sum[i]*C(n+sum[n]-1, sum[n]))%mod;
ans=(ans+w[i]*tem)%mod;
}
printf("%lld\n", (ans%mod+mod)%mod);
}
}
signed main()
{
// freopen("box.in", "r", stdin);
// freopen("box.out", "w", stdout);
int T=read();
fac[0]=fac[1]=1; inv[0]=inv[1]=1;
for (int i=2; i<N; ++i) fac[i]=fac[i-1]*i%mod;
for (int i=2; i<N; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<N; ++i) inv[i]=inv[i-1]*inv[i]%mod;
while (T--) {
n=read();
for (int i=1; i<=n; ++i) a[i]=read();
for (int i=1; i<n; ++i) w[i]=read();
// force::solve();
task::solve();
}
return 0;
}