P9149 串串题 Sol
调了半天,原因是在没有输入 的情况下 大小的 。
很直观的做法是把 中没有在 中出现过的数删掉,生成 。
记录一个 表示每一个 中的元素原来在 中的位置。
那么 中对于每一个长度为 的区间 ,可以发现,如果要它与 匹配,那么需要在 数组中删掉满足 且没有在 中出现过的数 。令这些 去重后个数为 。
钦定这 个数之后,发现这个区间外面的数随便删。
令 表示在 中没出现过的数的个数。
那么方案数显然就是在没出现的剩余 个数中选择 个数。
也就是 ,如此平移区间就可以计算啦。
#include <bits/stdc++.h>
#define int long long
using ull = unsigned long long;
using namespace std;
const int N = 1e6 + 10, P = 1e9 + 7;
const ull bas = 998244853; ull pw[N], has[N];
int t, n, m, w, d, a[N], b[N];
int inv[N], fac[N], ifac[N];
inline void init() {
inv[0] = inv[1] = fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
pw[0] = 1, pw[1] = bas;
for (int i = 2; i <= 1e6; ++i) {
inv[i] = inv[P % i] * (P - P / i) % P;
fac[i] = fac[i - 1] * i % P, ifac[i] = ifac[i - 1] * inv[i] % P;
pw[i] = pw[i - 1] * bas;
}
return ;
}
inline int C(int x, int y) {
if (x < 0 || y < 0 || x < y) return 0;
return fac[x] * ifac[y] % P * ifac[x - y] % P;
} inline ull query(int l, int r) {
return has[r] - pw[r - l + 1] * has[l - 1];
}
inline void solve() {
vector <int> g, cnt; vector <bool> vis;
cin >> n >> m >> w >> d; ull H = 0;
g.push_back(0), cnt.resize(w + 10), vis.resize(w + 10);
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= m; ++i) {
cin >> b[i], vis[b[i]] = true;
H = H * bas + b[i];
}
for (int i = 1; i <= n; ++i) if (vis[a[i]]) g.push_back(i);
int siz = 0, all = 0, res = 0, len = g.size() - 1;
if (len < m) return cout << 0 << endl, void();
for (int i = 1; i <= w; ++i) if (!vis[i]) ++all;
for (int i = 1; i <= m; ++i) has[i] = has[i - 1] * bas + a[g[i]];
for (int i = g[1]; i <= g[m]; ++i)
if (!vis[a[i]]) if (++cnt[a[i]] == 1) ++siz;
(res += (query(1, m) == H) * C(all - siz, d - siz)) %= P;
for (int i = 2; i + m - 1 <= len; ++i) {
for (int j = g[i - 1]; j < g[i]; ++j)
if (!vis[a[j]]) if (!(--cnt[a[j]])) --siz;
for (int j = g[i + m - 2] + 1; j <= g[i + m - 1]; ++j)
if (!vis[a[j]]) if (++cnt[a[j]] == 1) ++siz;
has[i + m - 1] = has[i + m - 2] * bas + a[g[i + m - 1]];
(res += (query(i, i + m - 1) == H) * C(all - siz, d - siz)) %= P;
}
return cout << res << endl, void();
}
signed main() {
ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0);
init(); cin >> t; while (t--) solve(); return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现