【LOJ】#6433. 「PKUSC2018」最大字首和
阿新 • • 發佈:2018-12-14
題解
神仙的狀壓啊QAQ
設一個\(f[S]\)表示數字的集合為\(S\)時\(sum[S]\)為字首最大值的方案數
\(g[S]\)表示數字集合為\(S\)時所有字首和都小於等於0的方案數
答案就是\(sum_{S} sum[S] * f[S] * g[2^{N} - 1 - S]\)
求\(f\)每次相當於往前面插入一個數,如果\(sum[S] > 0\)就更新
\(f[S ^ (1 << i - 1)] += f[S] (sum[S] > 0)\)
求\(g\)只要每次看看更新的集合總和是不是合法就行了
程式碼
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 998244353; int N; int A[25],sum[(1 << 20) + 5],pos[(1 << 20) + 5],f[(1 << 20) + 5],g[(1 << 20) + 5],ans; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } int lowbit(int x) { return x & (-x); } void update(int &x,int y) { x = inc(x,y); } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) read(A[i]); for(int i = 0 ; i < N ; ++i) pos[1 << i] = i + 1; for(int S = 1 ; S < (1 << N) ; ++S) { sum[S] = sum[S ^ lowbit(S)] + A[pos[lowbit(S)]]; } g[0] = 1; for(int i = 1 ; i <= N ; ++i) { f[1 << i - 1] = 1; } for(int S = 1 ; S < (1 << N) ; ++S) { if(sum[S] > 0) { for(int i = 1 ; i <= N ; ++i) { if(!(S >> (i - 1) & 1)) { update(f[S ^ (1 << i - 1)],f[S]); } } } else { for(int i = 1 ; i <= N ; ++i) { if(S >> (i - 1) & 1) { update(g[S],g[S ^ (1 << i - 1)]); } } } } for(int S = 1 ; S < (1 << N) ; ++S) { int t = mul(f[S],g[(1 << N) - 1 - S]); t = mul(t,inc(MOD,sum[S])); update(ans,t); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }