Official

F - #(subset sum = K) with Add and Erase Editorial by en_translator


If this problem only has operations of type \(1\) (addition), one can perform a DP (Dynamic Programming) where \(dp\) [ partial sum ] \(=\) { count }. We will try to extend this method to support deletion too.

On addition, the transition of the DP is as follows:

  • for each \(i=K,K-1,\dots,x+1,x\) in this order,
    • add \(dp[i-x]\) to \(dp[i]\).

Its inverse operation is the correct transition of DP on removal:

  • for each \(i=x,x+1,\dots,K-1,K\) in this order,
    • subtract \(dp[i-x]\) from \(dp[i-x]\).

Note that one has to store \(dp\) only for the indices \(0,1,\dots,K\). (The value \(dp[K+1]\) and later does not affect to \(dp[K]\) and prior.)

Sample code (C++):

#include<bits/stdc++.h>
#define mod 998244353

using namespace std;

int dp[5005]={0};

int main(){
  int q,k;
  cin >> q >> k;
  dp[0]=1;
  while(q>0){
    q--;
    string s;
    int x;
    cin >> s >> x;
    if(s=="+"){
      for(int i=k;i>=x;i--){
        dp[i]+=dp[i-x];
        dp[i]%=mod;
      }
    }
    else{
      for(int i=x;i<=k;i++){
        dp[i]+=(mod-dp[i-x]);
        dp[i]%=mod;
      }
    }
    cout << dp[k] << "\n";
  }
  return 0;
}

posted:
last update: