zoukankan      html  css  js  c++  java
  • ICPC2008哈尔滨-A-Array Without Local Maximums

    题目描述

    Ivan unexpectedly saw a present from one of his previous birthdays. It is array of n numbers from 1 to 200. Array is old and some numbers are hard to read. Ivan remembers that for all elements at least one of its neighbours ls not less than it, more formally:
    a1≤a2,
    an≤an−1 and
    ai≤max(ai−1,ai+1) for all i from 2 to n−1.
    Ivan does not remember the array and asks to find the number of ways to restore it. Restored elements also should be integers from 1 to 200. Since the number of ways can be big, print it modulo 998244353.

    输入

    First line of input contains one integer n (2≤n≤105) — size of the array.

    Second line of input contains n integers ai — elements of array. Either ai=−1 or 1≤ai≤200. ai=−1 means that i-th element can't be read.

    输出

    Print number of ways to restore the array modulo 998244353.

    样例输入

    3
    1 -1 2
    

    样例输出

    1
    题意
    构造一个长度为n的序列,有些位置是-1,可以填1-200的数字,要使得每个位置都比它左右两侧的最大值小,求方案数
    
    思路
    dp
    f[i][j][0/1/2]表示到第i位,当前数为j,从i-1到i是上升/相等/下降的方案数
    显然
    f[i][j][0]=f[i-1][k][0]+f[i-1][k][1]+f[i-1][k][2]; k<j;
    f[i][j][1]=f[i-1][k][0]+f[i-1][k][1]+f[i-1][k][2]; k=j
    f[i][j][2]=f[i-1][k][1]+f[i-1][k][2];
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int P=998244353;
    const int N=1e5+10;
    ll f[N][205][3];
    ll sum[2][205][3];
    int a[N];
    int n;
    int main(){
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
     
        if (a[1]==-1)
        {
            for (int i=1;i<=200;i++) f[1][i][0]=1;
        } else f[1][a[1]][0]=1;
     
        for(int i = 1; i <= 200; i++) sum[0][i][0] = (sum[0][i-1][0] + f[1][i][0])%P;
     
        for (int i=2;i<=n;i++) {
            //sum[!(i&1)][0][0] = sum[!(i&1)][0][1] = sum[!(i&1)][0][2] = 0;
            for (int j=1;j<=200;j++) {
            if (a[i]==-1 ||  a[i]==j)
            {
                //f[i][j][0]=f[i-1][k][0]+f[i-1][k][1]+f[i-1][k][2]; k<j;
                f[i][j][0]=((sum[i&1][j-1][0]+sum[i&1][j-1][1])%P+sum[i&1][j-1][2])%P;
                //f[i][j][1]=f[i-1][k][0]+f[i-1][k][1]+f[i-1][k][2]; k=j
                f[i][j][1]=(f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2])%P;
                //f[i][j][2]=(f[i][j][2]+f[i-1][k][1]+f[i-1][k][2])%p;
                f[i][j][2]=((sum[i&1][200][1] - sum[i&1][j][1] +P)%P + (sum[i&1][200][2] - sum[i&1][j][2]+P)%P)%P;
     
            }
            sum[!(i&1)][j][0] = (sum[!(i&1)][j-1][0] + f[i][j][0])%P;
            sum[!(i&1)][j][1] = (sum[!(i&1)][j-1][1] + f[i][j][1])%P;
            sum[!(i&1)][j][2] = (sum[!(i&1)][j-1][2] + f[i][j][2])%P;
            }
        }
       // cout<<f[1][a[1]][0]<<' '<<f[1][a[1]][1]<<' '<<f[1][a[1]][2]<<endl;
        ll ans=0;
        if (a[n]==-1)
        {
            for (int i=1;i<=200;i++)
            {
               // printf("f[3][%d][0]=%lld,f[3][%d][1]=%lld,f[3][%d][2]=%lld
    ",i,f[3][i][0],i,f[3][i][1],i,f[3][i][2]);
                ans=(ans+f[n][i][1]+f[n][i][2])%P;
            }
        } else ans=(f[n][a[n]][1]+f[n][a[n]][2])%P;
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
    k>j
    枚举k的话是200*200*n,所以要前缀和优化……但可能写的过于诡异

     

  • 相关阅读:
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Number Challenge(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)
    Python位运算符
  • 原文地址:https://www.cnblogs.com/tetew/p/11317677.html
Copyright © 2011-2022 走看看