Xiangtan Invitation Contest 2017

来源:互联网 发布:三菱人机界面怎么编程 编辑:程序博客网 时间:2024/05/22 02:27

For given sequence A = (a1, a2, . . . , an), a sequence S = (s1, s2, . . . , sn) has shape A 

if and only if:• si = min{si, si+1, . . . , sn} for all ai = 0;• si = max{si, si+1, . . . , sn} for all ai = 1.

Given sequence B = (b1, b2, . . . , bm), Bobo would like to know the number of subsequences of length n whichhave shape A modulo (109 + 7).


分析:f[i,j,x,y]表示当前匹配到a的第i个位置,b的第j个位置,最大值为x,最小值为y的方案数,那么下一个决策就是f[i+1,j',x',y'] 其中j' > j且b[j] ∈[x,y],注意到x 和 y中一定有一个等于b[j],这样可以把状态精简为f[i,j,k],k表示最大值或最小值,此时如果暴力转移复杂度是n*m^3,可以用树状数组优化到n*m^2*log(m).


#include <bits/stdc++.h>#define N 100005#define MOD 1000000007using namespace std;typedef long long ll;int n,m,a[25],b[505],f[25][505][505],p[25][505][505];bool could(int i,int j,int k){    if(a[i]) return b[j] >= k;    else return b[j] <= k;}void Insert(int i,int j,int k,int x){    while(k <= m)    {        p[i][j][k] += x;        p[i][j][k] %= MOD;        k += k & (-k);    }}int Find(int i,int j,int k){    int ans = 0;    while(k)    {        ans = ans + p[i][j][k];        ans %= MOD;        k -= k & (-k);    }    return ans;}int main(){    while(scanf("%d%d",&n,&m) != EOF)    {        memset(p,0,sizeof(p));        memset(f,0,sizeof(f));        for(int i = 1;i <= n;i++) scanf("%d",&a[i]);        for(int i = 1;i <= m;i++) scanf("%d",&b[i]);        for(int j = m;j;j--)        {            for(int i = n;i;i--)             for(int k = 1;k <= m;k++)              if(could(i,j,k))              {                  int l = min(k,b[j]),r = max(k,b[j]);                  int c = a[i+1] ? l : r;                  if(i == n) f[i][j][k] = 1;                  else f[i][j][k] = (Find(i+1,c,r) - Find(i+1,c,l-1) + MOD) % MOD;              }            for(int i = n;i;i--)             for(int k = 1;k <= m;k++)              if(could(i,j,k)) Insert(i,k,b[j],f[i][j][k]);        }        int ans = 0;        for(int j = 1;j <= m;j++)        {            if(a[1]) ans = (ans + f[1][j][1]) % MOD;            else ans = (ans + f[1][j][m]) % MOD;        }        printf("%d\n", ans);    }}


原创粉丝点击