D. Caesar's Legions (classic count dp)

https://codeforces.com/problemset/problem/118/D


The big guy said it was very spicy

Codeforces 118D Caesar's Legions【dp】Good question

Main idea:

There are n1 numbers 1 and n2 numbers 2 (see the translation of Note, I don’t know if the original text is the same)

Arrange n1+n2 digits in a row, which requires a maximum of k1 for consecutive digits and k2 for consecutive digits.

Ask how many distribution plans are there.

 

Ideas:

 

1. For statistical counting problems, consider dp.

Set dp[i][j1][j2][k1][k2][l(2)], which means dp to the i-th digit, and the current number type is l, where the number 1 uses j1 and the number 2 uses There are j2, and the number of consecutive l (assumed to be 0) before the last number (the current number) is k1, and there are a total of k2 schemes for another consecutive number before. Obviously it can cover all situations, because the memory limit includes time limit, we consider reducing the dimension of this array.

In fact, we only consider the current figures, then:

Set dp[i][j][k][l(2)], which means that the current dp to the i-th digit, the current number type is l, corresponding to the current number l has been used j, and the last number (current number ) There are a total of k solutions for the previous consecutive l.

 

2. After setting the dp array, consider recursively deriving its state transition equation (at this time, l==0 means that the number added above is 1, and l==1 means that the number of the sky sword above is 2):

if(k==1)
dp【i】【j】【k】【0】+=dp【i-1】【i-j】【kk】【1】;

It means that our current number on the i-th seat is different from the number on the i-1th seat, so we need to consider the state of the previous one. First of all, we know that when the i-1th seat is at the time, there is a total number i- 1, corresponding to which must contain j-1 number 1, then the number containing number 2 is: i-1-(j-1)=ij; then we need to enumerate such a variable again: because we If the number on the i-1th position is 2, then we need to know the number of consecutive 2s at this time. Then we can enumerate one more kk.

if(k>1)

dp【i】【j】【k】【0】+=dp【i-1】【j-1】【k-1】【0】;

Indicates that our current number on the i-th position is the same as the number on the i-1th position, then corresponds to the state of our previous position: from dp to the i-1th position, the number of numbers 1 already used is j-1, The number corresponding to the consecutive number 1 is k-1. Just add it up directly.

Similarly, the corresponding:

if(k==1)

dp【i】【j】【k】【1】+=dp【i-1】【i-j】【kk】【0】;

if(k>1)

dp【i】【j】【k】【1】+=dp【i-1】【j-1】【k-1】【1】;

 

3. Pay attention to taking the modulus of 1e8, pay attention to the initialization, the others are nothing.


#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=210;
typedef int LL;
LL dp[maxn][maxn][maxn][3];
const LL mod=1e8;
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n1,n2,k1,k2;cin>>n1>>n2>>k1>>k2;
  dp[1][1][1][1]=1;
  dp[1][1][1][2]=1;
  for(LL i=2;i<=n1+n2;i++){
    ///当前数字类型为1时
    for(LL j=1;j<=i&&j<=n1;j++){
        for(LL k=1;k<=k1;k++){
            if(k==1){
                for(LL kk=1;kk<=k2;kk++){
                    dp[i][j][k][1]+=dp[i-1][i-j][kk][2];
                    dp[i][j][k][1]%=mod;
                }
            }
            else{
                dp[i][j][k][1]+=dp[i-1][j-1][k-1][1];
                dp[i][j][k][1]%=mod;
            }
        }
    }
    ///当前数字类型为2时
    for(LL j=1;j<=i&&j<=n2;j++){
        for(LL k=1;k<=k2;k++){
            if(k==1){
                for(LL kk=1;kk<=k1;kk++){
                    dp[i][j][k][2]+=dp[i-1][i-j][kk][1];
                    dp[i][j][k][2]%=mod;
                }
            }
            else{
                dp[i][j][k][2]+=dp[i-1][j-1][k-1][2];
                dp[i][j][k][2]%=mod;
            }
        }
    }
  }
  LL ans=0;
  for(LL i=1;i<=k1;i++){
    ans=(ans%mod+dp[n1+n2][n1][i][1]%mod)%mod;
  }
  for(LL i=1;i<=k2;i++){
    ans=(ans%mod+dp[n1+n2][n2][i][2]%mod)%mod;
  }
  cout<<ans<<endl;
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/113094177