2024.10.21 CW 模拟赛
T2
概率 \(dp\)
考虑从后往前递推, 令 \(f_{i,j}\) 表示后 \(i\) 步, 当前位置为 \(j\) 的概率.
那么显然, \(j \in [n-i+1,n+i-1]\). (因为 \(a_i \in \{-1,1\}\) ,所以在后 \(i\) 步的时候, 前面操作了 \(n-i\) 次, 最多只有可能在 \([n-i+1,n+i-1]\) 这个范围内)
那为什么不从前往后递推呢?
如果考虑从前往后, 不好考虑当前位置对答案的影响.
但如果从后往前考虑, 当前位置对答案的影响就非常简单, 只需要赋值为1即可.
转移就很简单了.
#include "iostream"
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T &x){
x=0; bool f=1; char ch=getchar();
while (!isdigit(ch)){
if (ch=='-') f=!f;
ch=getchar();
}
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
x=(f?x:-x);
return;
}
template<typename T>
void print(T x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
return;
}
const int N=5e3+1,mod=1e9+7;
int n;
int ps,pm;
short a[N];
ll f[2][N<<1];//滚动数组
int main(){
read(n); read(ps);
for (int i=1;i<=n;++i) read(a[i]);
int dn=n<<1;
ps=1ll*570000004*ps%mod,pm=(1-ps+mod)%mod;
f[0][n]=1;
for (int i=1;i<=n;++i){
int x=i&1,y=i&1^1;
for (int j=n-i+1;j<=n+i-1;++j){
(f[x][j]+=ps*f[y][j])%=mod;
(f[x][j+a[n-i+1]]+=pm*f[y][j])%=mod;
}
for (int j=0;j<=dn;++j) f[y][j]=0;
f[x][n]=1;
}
int x=n&1;
for (int i=0;i<=dn;++i) print(f[x][i]),putchar(' ');
return 0;
}
T3
- 引理: 一个长度为 \(2n\) 的括号串合法, 当且仅当所有左括号的位置能被 \(1,3,5,7...,2n+1\) 偏序.
- 证明:
不难发现这个形式等价于括号前缀函数 \(\ge 0\). - 正解: 令 \(nxt_i\) 表示 \(a_i\) 右侧对应的位置.
于是我们就可以看成是左括号的位置和 \(1,3,5,7,...,2n+1\) 的匹配.
考虑从前往后扫, 假设遇到 \(i\) 且 \(a_i\) 还没确定, 如果 \(nxt_i\) 的可以选择匹配, 那就拿去匹配.
时间复杂度 \(\mathcal{O}(n \log n)\).
#include "iostream"
#include "set"
using namespace std;
const int N = 2e6 + 10;
template<typename T>
inline void read(T &x) {
x = 0;
char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return;
}
int n;
int nxt[N], h[N];
bool ans[N];
set<int> s;
int main() {
read(n);
int dn = n << 1;
for (int i = 1; i <= dn; ++i) {
int x;
read(x);
nxt[h[x]] = i;
h[x] = i;
}
for (int i = 1; i <= n; ++i) s.insert((i << 1) - 1);
for (int i = 1; i <= dn; ++i) if (nxt[i]) {
if (!s.empty() and *s.rbegin() >= nxt[i]) {
s.erase(s.lower_bound(nxt[i]));
auto x = s.lower_bound(i);
if (x == s.end()) return puts(":("), 0;
s.erase(x), ans[i] = ans[nxt[i]] = 1;
}
}
if (!s.empty()) return puts(":("), 0;
for (int i = 1; i <= dn; ++i) putchar(ans[i] ? '(' : ')');
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现