Tencent written - colored buildings

# Colored buildings

\[ Time Limit: 5000 ms \quad Memory Limit: 262144 kB \]

topic

You small Q l, 2,3 ... n The number n, n represents a floor, the height of the i-th floor, is i, each floor has a color
will now be made of these building randomly arranged in a straight line , Q how many kinds of arrangements, to meet the right to see the leftmost (left standing to see far away) to see the change L-1 variant of color views, the answer to 1e9 + 9 modulo
the height of the floor of the same color if the two respectively H1, H2 (H1 <H2) , H1 on the left, and between H1 H2 H1 shorter than the floor, then standing on the left to see is a kind of color
you can see a building on the premise that before this building it is shorter than the floor

input

The first line of the input two integers n, L (1 <= n <= 1296), (1 <= L <n =)
The second row input n integers Ci denotes a color of each floor (1 <= Ci <= n)

output

Output an integer representing the number of programs, and 1e9 + 9 mod

Thinking

The following reference Xiamen practice a Gangster ...

step1

\ (O (N ^ 3) \) violent \ (DP \) , forward from the \ (DP \) .
\ (dp [i] [k ] [j] \) represents the section \ (I \) when a building, can be seen \ (K \) colors, and the left floor color \ (J \) .
For \ (dp [i] [k ] [j] \) following transfer:

  1. Consider first floor is left \ (I \) behind the floor, the \ (I \) floor to go into the back, then there is
    \ [dp [i] [k ] [j] = dp [i + 1 [k ] [j] * (ni) \]
  2. Consider the left-most floor is \ (I \) floors, i.e. if (j == a [i] \ ) \ When there
    \ [dp [i] [k ] [j] + = dp [i + 1] [k] [j] \\ dp [i] [k] [j] + = dp [i + 1] [k-1] [\ sum_ {j '= 1} ^ {j' \ neq j} j ' ] \]
    because of the presence \ (j '\ neq j \ ) is determined, in \ (for \) again is a waste of time, you can start an array \ (SUM \) , \ ([I SUM] [K] \) represents \ (\ sum_. 1} = {J ^ {J} = n-DP [I] [K] [J] \) , followed by subtraction answer.

Time complexity \ (O (N ^ 3) \) , the space complexity \ (O (N ^ 3)
\) Code :( This code can be run \ (n-\) in \ (500 \) or less)

void solve1() {
    mes(sum, 0);
    dp[n][1][a[n]] = 1;
    sum[n][1] = 1;
    for(int i=n-1; i>=1; i--) {
        for(int k=1; k<=m; k++) {
            for(int j=1; j<=n; j++) {
                if(j == a[i]) {
                    dp[i][k][j] = (dp[i+1][k][j]*(n-i+1)%mod+sum[i+1][k-1]-dp[i+1][k-1][j])%mod+mod;
                    dp[i][k][j] %= mod;
                } else {
                    dp[i][k][j] = dp[i+1][k][j]*(n-i)%mod;
                }
                sum[i][k] = (sum[i][k] + dp[i][k][j])%mod;
            }
        }
    }
    printf("%lld\n", sum[1][m]);
}

step2

Not difficult to find by looking at the equation, because the \ (k \) only and (k-1 \) \ answers about, as long as the descending enumeration \ (k \) , the first dimension can be optimized rolling away.
Observation code, we found that the third layer cycle, only when \ (j == a [i] \) , the transfer is more complex for other \ (J \) , the transfer process is exactly the same. So we can simplify this layer cycle.
First, this layer circulation in the equation as much as possible extracted.
For \ (DP \) equation can be calculated directly \ (j == a [i] \) case, the \ (j \ neq a [i ] \) case remain in the \ (for \) in. This step is very easy to do.
For \ (SUM \) equation, can be found in \ (j \ neq a [i ] \) section, \ (DP \) integrally by \ (Ni \) , so this part can be written as \ (sum [k] * ( Ni) -dp [K] [J] * (Ni) \) , then add the calculated special \ (j == a [i] \) case of \ (DP \)Value on it.
Time complexity \ (O (N ^. 3) \) , the space complexity \ (O (N ^ 2) \)

void solve2() {
    mes(sum, 0);
    dp[1][a[n]] = 1;
    sum[1] = 1;
    for(int i=n-1; i>=1; i--) {
        for(int k=m; k>=1; k--) {
            {
                int j = a[i];
                sum[k] = ((sum[k]*(n-i)%mod - dp[k][j]*(n-i)%mod)%mod+mod)%mod;
                dp[k][j] = (dp[k][j]*(n-i+1)%mod+sum[k-1]-dp[k-1][j])%mod+mod;
                dp[k][j] %= mod;
                sum[k] = (sum[k] + dp[k][j])%mod;
            }
            for(int j=1; j<=n; j++) {
                if(j != a[i]) {
                    dp[k][j] = dp[k][j]*(n-i)%mod;
                }
                // printf("dp[%d][%d] = %lld\n", k, j, dp[k][j]);
            }
        }
    }
    printf("%lld\n", sum[m]);
}

step3

Or think of ways to cycle on the third floor, we see this layer in addition to \ (j == a [i] \) outside are multiplied by a \ ((Ni) \) , then if we let \ (j = = a [i] \) while also multiplied by a \ ((Ni) \) , can be unified whole dimension \ (DP \) a. Then we can be saved when saving \ (\ frac {dp [k ] [j]} {(ni)} \) value, when in operation due to the original value multiplied back on it.
Since each \ (I \) should be multiplied by a \ (\ FRAC. 1} {Ni} {\) , that is to say for the first \ (I \) a building, the carpool on a \ (\ FRAC {1} {\ prod_ {x
= 1} ^ {x} nx} \) this step can also be done, as long as each of the operational \ (j == a [i] \) , the so \ (dp [k ] [j] \) multiplied he should be reduced multiples on it.
After this treatment, the time complexity \ (O (N ^ 2) \) , the space complexity \ (O (N ^ 2) \)

/*************************************************************** 
    > File Name    : a.cpp
    > Author       : Jiaaaaaaaqi
    > Created Time : Tue 10 Sep 2019 10:21:23 PM CST
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e3 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 9;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

ll n, m;
int cas, tol, T;

ll sum[maxn];
ll dp[maxn][maxn];
ll a[maxn];

ll fpow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b&1) ans = ans*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return ans;
}

int main() {
    // freopen("in", "r", stdin);
    scanf("%lld%lld", &n, &m);
    for(int i=1; i<=n; i++) {
        scanf("%lld", &a[i]);
    }
    mes(sum, 0);
    dp[1][a[n]] = 1;
    sum[1] = 1;
    ll base = 1;
    for(int i=n-1; i>=1; i--) {
        for(int k=m; k>=1; k--) {
            {
                int j = a[i];
                sum[k] = ((sum[k]*(n-i)%mod - dp[k][j]*(n-i)%mod*base%mod)%mod+mod)%mod;
                dp[k][j] = ((dp[k][j]*base%mod*(n-i+1)%mod+sum[k-1])%mod-dp[k-1][j]*base%mod)%mod+mod;
                dp[k][j] %= mod;
                sum[k] = (sum[k] + dp[k][j])%mod;
                dp[k][j] = dp[k][j] * fpow(base*(n-i)%mod, mod-2)%mod;
                // printf("dp[%d][%d] = %lld\n", k, j, dp[k][j]*base);
            }
        }
        base = base*(n-i)%mod;
    }
    printf("%lld\n", sum[m]%mod);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Jiaaaaaaaqi/p/11504103.html