【LOJ 6433] [PKUSC 2018]最大プレフィックスと
問題の意味
長さを考えると\(N- \)のシーケンスを、このランダムシーケンスは、所望の動揺を掛けた後に最大プレフィックスを求めて\(N-!\)の後に\(998244353 \)フィルムを取る値。
プレフィックスと空にすることはできません。
\(N 20 \を\) 。
問題の解決策
まず、この期待は明らかにあなたをからかっている...それを数えます
我々は2つの部分のシーケンスに分割され、接頭辞の合計よりも大きくない、プレフィックス部分とないより大きい\(0 \) 。これまでのところ、このようなシーケンスの最大プレフィックスと最初の部分であり、我々はちょうど知っていますどのように多くのこのような配列だけで罰金。
ビット平均感じの練習の後ろ
我々は2つの部分から構成されるプログラムシーケンスの数のサブセットを解決する2つの倍精度を使用している。現在の設定よりも大きい場合(\ 0 \)次に、明らかに第2の部分を形成するために使用され、我々は正当このセットで生成されるわけではありません第一の部分の新しい値を形成するために、前部の第1の部分を加える。現在のセットよりも大きくない場合(\ 0 \) 、それは唯一の第二の部分を構成するために使用することができ、これは帝国Aを設定すると結論付けることができる場合端部に配置された値があれば、残りの値が正当な第二の部分を構成することができるように、新たなシーケンスは、正当な第二の部分を構成することができます。
最後の最初の部分では、これらの値は、残りの値投げの2番目の部分は、それをロールアップする列挙。
参照コード
#include <bits/stdc++.h>
const int MAXN=21;
const int MOD=998244353;
const int MAXL=(1<<20)|3;
int n;
int a[MAXN];
int dp1[MAXL];
int dp2[MAXL];
int sum[MAXL];
inline int LowBit(int);
int main(){
scanf("%d",&n);
dp2[0]=1;
for(int i=0;i<n;i++){
scanf("%d",a+i);
dp1[1<<i]=1;
sum[1<<i]=a[i];
}
for(int s=1;s<(1<<n);s++){
if(s!=LowBit(s))
sum[s]=sum[s^LowBit(s)]+sum[LowBit(s)];
if(sum[s]>0){
for(int i=0;i<n;i++)
if((s&(1<<i))==0)
(dp1[s^(1<<i)]+=dp1[s])%=MOD;
}
else{
for(int i=0;i<n;i++)
if((s&(1<<i))!=0)
(dp2[s]+=dp2[s^(1<<i)])%=MOD;
}
}
int ans=0;
for(int s=1;s<(1<<n);s++)
(ans+=1ll*sum[s]*dp1[s]%MOD*dp2[((1<<n)-1)^s]%MOD)%=MOD;
printf("%d\n",ans<0?ans+MOD:ans);
return 0;
}
inline int LowBit(int x){
return x&-x;
}