\(\mathcal{Description}\)

  Link.

  给定长度为 \(n\) 的合法表达式序列 \(s\),其中数字仅有一位正数,运算符仅有 - 作为占位。求将其中恰好 \(k\) 个 - 替换为 +,其余 - 替换为 * 的所有方案得到的表达式结果之和。答案模 \((10^9+7)\)。

  \(n\le10^5\)(可能有无意义的多层括号嵌套),- 的总数 \(m\le2.5\times10^3\)。

\(\mathcal{Solution}\)

  复杂表达式问题,应当考虑按匹配括号建树,并在树上 DP。

  考虑树上结点 \(u\) 以及它的孩子们 \(v_1,\cdots,v_c\),它们代表了形如 u=(v1)-(v2)-...-(vc) 的表达式。令 \(f_{u,i}\) 表示 \(u\) 从左到右合并了一些孩子,用了 \(i\) 个 + 时,所有表达式结果之和;\(g_i\) 表示 \(u\) 从左到右合并了一些孩子,用了 \(i\) 个 + 时,所有后缀乘积之和。设已合并的孩子们共有 \(s_u\) 个 +,现欲合并孩子 \(v\),其有 \(s_v\) 个 +,转移分 +, * 讨论:

\[\begin{aligned}f'_{u,i+j+1}&\longleftarrow^+\binom{s_v}{j}f_{u,i}+\binom{su}{i}f_{v,j},\\f'_{u,i+j}&\longleftarrow^+\binom{s_v}{j}(f_{u,i}-g_i)+g_if_{v,i},\\g'_{i+j+1}&\longleftarrow^+\binom{s_u}{i}f_{v,j},\\g'_{i+j}&\longleftarrow^+g_if_{v,j},\\s_u&\longleftarrow^+s_v+1.\end{aligned}
\]

  转移复杂度是树上背包,总复杂度 \(\mathcal O(n+m^2)\)。

\(\mathcal{Code}\)

/*~Rainybunny~*/

#pragma GCC optimize( "Ofast" )

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) const int MAXN = 2e5, MAXM = 5e3, MOD = 1e9 + 7;
int n, k, m, node, siz[MAXM + 5], mtc[MAXN * 3 + 5];
int comb[MAXM + 5][MAXM + 5], f[MAXM + 5][MAXM + 5];
char str[MAXN * 3 + 5], tmps[MAXN + 5]; inline int imin( const int u, const int v ) { return u < v ? u : v; }
inline int imax( const int u, const int v ) { return u < v ? v : u; }
inline int mul( const int u, const int v ) { return 1ll * u * v % MOD; }
inline int sub( int u, const int v ) { return ( u -= v ) < 0 ? u + MOD : u; }
inline int add( int u, const int v ) { return ( u += v ) < MOD ? u : u - MOD; }
inline void addeq( int& u, const int v ) { ( u += v ) >= MOD && ( u -= MOD ); } inline void init() {
int len = n; n = 0;
rep ( i, 1, len ) {
if ( '0' <= tmps[i] && tmps[i] <= '9' ) {
str[++n] = '(', str[++n] = tmps[i], str[++n] = ')';
} else {
str[++n] = tmps[i];
m += tmps[i] == '-';
}
} static int stk[MAXN * 3 + 5]; int top = 0;
rep ( i, 1, n ) {
if ( str[i] == '(' ) stk[++top] = i;
else if ( str[i] == ')' ) mtc[mtc[stk[top]] = i] = stk[top], --top;
} comb[0][0] = 1;
rep ( i, 1, m ) {
comb[i][0] = 1;
rep ( j, 1, i ) comb[i][j] = add( comb[i - 1][j - 1], comb[i - 1][j] );
}
} inline int solve( int l, int r ) {
if ( mtc[l] == r ) return solve( l + 1, r - 1 );
int u = ++node, *fu = f[u];
if ( l == r ) return fu[0] = str[l] ^ '0', u; int g[MAXM + 5];
for ( int p = l, v, fir = true; p < r; ) {
if ( str[p] != '(' ) { ++p; continue; }
const int *fv = f[v = solve( p, mtc[p] )]; p = mtc[p] + 1; if ( fir ) {
rep ( i, 0, siz[v] ) fu[i] = g[i] = fv[i];
siz[u] = siz[v], fir = false;
continue;
} static int tmp[MAXM + 5];
rep ( i, 0, siz[u] ) rep ( j, 0, siz[v] ) {
addeq( tmp[i + j + 1], add( mul( fu[i], comb[siz[v]][j] ),
mul( fv[j], comb[siz[u]][i] ) ) );
addeq( tmp[i + j], add( mul( sub( fu[i], g[i] ),
comb[siz[v]][j] ), mul( g[i], fv[j] ) ) );
}
rep ( i, 0, siz[u] + siz[v] + 1 ) fu[i] = tmp[i], tmp[i] = 0;
rep ( i, 0, siz[u] ) rep ( j, 0, siz[v] ) {
addeq( tmp[i + j], mul( g[i], fv[j] ) );
addeq( tmp[i + j + 1], mul( comb[siz[u]][i], fv[j] ) );
}
rep ( i, 0, siz[u] + siz[v] + 1 ) g[i] = tmp[i], tmp[i] = 0;
siz[u] += siz[v] + 1;
}
return u;
} int main() {
freopen( "operator.in", "r", stdin );
freopen( "operator.out", "w", stdout ); scanf( "%d %d %s", &n, &k, tmps + 1 );
init(); //, fprintf( stderr, "%s\n", str + 1 );
printf( "%d\n", f[solve( 1, n )][k] );
return 0;
}

Solution -「多校联训」消失的运算符的更多相关文章

  1. Solution -「多校联训」排水系统

    \(\mathcal{Description}\)   Link.   在 NOIP 2020 A 的基础上,每条边赋权值 \(a_i\),随机恰好一条边断掉,第 \(i\) 条段的概率正比于 \(a ...

  2. Solution -「多校联训」I Love Random

    \(\mathcal{Description}\)   给定排列 \(\{p_n\}\),可以在其上进行若干次操作,每次选取 \([l,r]\),把其中所有元素变为原区间最小值,求能够得到的所有不同序 ...

  3. Solution -「多校联训」签到题

    \(\mathcal{Description}\)   Link.   给定二分图 \(G=(X\cup Y,E)\),求对于边的一个染色 \(f:E\rightarrow\{1,2,\dots,c\ ...

  4. Solution -「多校联训」朝鲜时蔬

    \(\mathcal{Description}\)   Link.   破案了,朝鲜时蔬 = 超现实树!(指写得像那什么一样的题面.   对于整数集 \(X\),定义其 好子集 为满足 \(Y\sub ...

  5. Solution -「多校联训」假人

    \(\mathcal{Description}\)   Link.   一种物品有 长度 和 权值 两种属性,现给定 \(n\) 组物品,第 \(i\) 组有 \(k_i\) 个,分别为 \((1,a ...

  6. Solution -「多校联训」古老的序列问题

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\),和 \(q\) 次形如 \([L,R]\) 的询问,每次回答 \[\sum_{[l,r]\su ...

  7. Solution -「多校联训」Sample

    \(\mathcal{Description}\)   Link   (稍作简化:)对于变量 \(p_{1..n}\),满足 \(p_i\in[0,1],~\sum p_i=1\) 时,求 \(\ma ...

  8. Solution -「多校联训」光影交错

    \(\mathcal{Description}\)   Link.   一个游戏包含若干次卡牌抽取,每次以 \(p_l\) 的概率得到 \(+1\),\(p_d\) 的概率得到 \(-1\),否则得到 ...

  9. Solution -「多校联训」数学考试

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个函数,第 \(i\) 个有 \(f_i(x)=a_ix^3+b_ix^2+cx_i+d~(x\in[l_i, ...

随机推荐

  1. 解决MySQL服务器禁止远程连接的问题

    1. 改表法. 可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库里的 " ...

  2. 第10组 Beta冲刺 (3/5)

    1.1基本情况 ·队名:今晚不睡觉 ·组长博客:https://www.cnblogs.com/cpandbb/p/14018630.html ·作业博客:https://edu.cnblogs.co ...

  3. Vue系列教程(三)之vue-cli脚手架的使用

    一.Vue-cli的环境准备 目的:(1)快速管理依赖 (2)确定项目结构 1.安装node.js Node.js是一个可以让前端运行在服务器上的一个工. 下载:https://nodejs.org/ ...

  4. Swagger的应用

    一.介绍 一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 框架. 二.依赖 <dependency> <groupId>io.springf ...

  5. test_1 计算字符串最后一个单词的长度,单词以空格隔开

    题目描述:计算字符串最后一个单词的长度,单词以空格隔开.  输入描述: 一行字符串,非空,长度小于5000. 输出描述: 整数N,最后一个单词的长度. #coding=utf-8 str = raw_ ...

  6. Mybatis配置解析(核心配置文件)

    4.配置解析 4.1.核心配置文件 Mybatis的配置文件包含了会深深影响mybatis行为的设置和属性信息 mybatis-config.xml properties(属性)重点 settings ...

  7. day 12 default后面是否还可以跟case

    (1).有以下程序: #include<stdio.h> void main(){ int case,float printF; printf("输入2个数\n"): ...

  8. 《剑指offer》面试题61. 扑克牌中的顺子

    问题描述 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2-10为数字本身,A为1,J为11,Q为12,K为13,而大.小王为 0 ,可以看成任意数字.A 不能视为 14. 示例 ...

  9. preg_match绕过总结

    preg_match绕过总结 什么是preg_match 绕过方法 1.数组绕过 preg_match只能处理字符串,当传入的subject是数组时会返回false 2.PCRE回溯次数限制 PHP利 ...

  10. JavaScript 中BOM的常用操作

    JavaScript BOM操作 1.获取浏览器窗口尺寸 var width=window,innerWidth //获取可视窗口宽度 var height=window.innerHeight // ...