传送门:Shuffle
给定一个二进制字符串,你可以对这个字符串进行最多一次如下的操作:
从$s$中选择一个正好有$k$个1字符的子串,然后你可以随意的打乱它。
计算可以从$s$经过这样一次操作之后能得到的不同的字符串的数量之和
从这道题的数据来看,$O(n^2)$的复杂度是能过的,一开始想过遍历所有的符合要求的字串,排列组合之后统计答案,但是这样的话重复的数量不是很好去除。
我们可以发现,经过一次操作之后,原字符串仅会被改变一个连续的部分,这个部分应该是一个合法的字串的一部分(因为可以只改变这个子串的一部分)。
我们就可以枚举这个连续的部分的两端,我们规定这两个端点是必须在一次操作之后被改变的,不然的话会有好几个:以010100举例,中间的1010是被选出来改过的,原来的字符串就必须是10xx10,这样就能够更简单的计算了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
   | #include<bits/stdc++.h> #define pii pair<int, int> #define pll pair<ll, ll> using namespace std; typedef long long ll;
  ll fastPower(ll base, ll power, ll mod) {     ll result = 1;     while (power > 0) {         if (power & 1) {             result = result * base % mod;         }         power >>= 1;         base = (base * base) % mod;     }     return result; }
  const ll MOD=998244353;
 
  ll fac[200010];         ll inv[200010];         void getfac() {     fac[0] = inv[0] = 1;     for (int i = 1 ; i <= 200000 ; i++)     {         fac[i] = fac[i-1] * i % MOD;         inv[i] = fastPower(fac[i], MOD-2, MOD);                      } }
  inline ll getC(ll n,ll m) {     return fac[n] * inv[n-m] % MOD * inv[m] % MOD; }
  inline ll Lucas(ll n,ll m) {     if(n < MOD && m < MOD) return getC(n, m);     return Lucas(n/MOD, m/MOD) * getC(n%MOD, m%MOD)%MOD; }
 
  inline ll getA(ll n,ll m)  { 	return n * inv[n-m] % MOD; }
  ll n, k, ans=1;
  void Main(int kase){     cin>>n>>k;
      char c;
      vector<ll> A(n+1), S(n+1);     for(ll i=1;i<=n;i++){         cin>>c;         A[i]=c-'0';         S[i]=S[i-1]+A[i];      }
      if(S[n]<k) {          cout<<1<<endl;         return;     }
      for(int i=1;i<=n;i++){         for(int j=i+1;j<=n;j++){             int cnt=j-i+1;             int cnt1=S[j]-S[i-1];
              if(cnt1>k) continue; 
              if(A[i]==0) cnt1--;             if(A[j]==0) cnt1--;
              cnt-=2;
              if(cnt1>=0 && cnt>=0 && cnt1<=cnt)                 ans=(ans+getC(cnt, cnt1))%MOD;         }     }
      cout<<ans<<endl; }
  int main(){     #ifdef DEBUG     freopen("in.txt", "r", stdin);     #endif          ios_base::sync_with_stdio(0);     cin.tie(0);     getfac();     Main(1);          return 0; }
   |