当前位置: 首页 > news >正文

P9041 [PA 2021] Fiolki 2 题解

Description

给定一张 \(n\) 个点的 DAG,保证点 \(1\sim k\) 没有入度,对每个 \(i\in[0,k]\),求出满足条件的区间 \([l,r]\subseteq(k,n]\) 的数量,使得起点在 \([1,k]\) 且终点在 \([l,r]\) 的极大不相交路径组大小为 \(i\)

\(n\leq 10^5,m\leq 10^6,k\leq 50\)

Solution

首先如果已知起点和终点的配对判断有没有解可以用 LGV 引理做,令 \(f_{i,j}\) 表示从 \(s_i\) 走到 \(t_j\) 的方案数,再对 \(f\) 求行列式判断结果是不是 \(0\) 即可。

这里方案数很多,需要对一个质数 \(P\) 取模,为了提高正确率,为每条边随一个边权,\(f_{i,j}\) 改成所有路径边权乘积之和。而行列式是否非零只需要判断其是否满秩即可。

然后考虑怎么对一个区间 \([l,r]\) 求答案。

设区间长度为 \(L\),设 \(a_{i,j}=f_{j,l+i-1}(1\leq i\leq L,1\leq j\leq k)\),问题变为找到最大的 \(x\),使得存在 \(a\) 的一个 \(x\times x\) 的子矩阵满秩。这是个线性代数经典结论,答案就是 \(a\) 的行秩。

\(V_{i,j}=f_{j,i}(k+1\leq i\leq n,1\leq j\leq k)\),那么我们只需要维护 \(V_{l},V_{l+1},\ldots,V_{r}\) 的线性基大小。

考虑扫描线,从小到大枚举 \(l\)。用时间戳线性基维护即可。

时间复杂度:\(O(nk^2+mk)\)

Code

#include <bits/stdc++.h>// #define int int64_tusing i64 = int64_t;
using u64 = uint64_t;const int kMaxN = 1e5 + 5, kMaxM = 1e6 + 5, kMaxK = 55, kMod = 998244353;int n, m, k;
int deg[kMaxN], val[kMaxM], tm[kMaxK];
i64 res[kMaxK];
std::vector<std::pair<int, int>> G[kMaxN];
std::mt19937_64 rnd(std::random_device{}());int qpow(int bs, int64_t idx = kMod - 2) {int ret = 1;for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)if (idx & 1)ret = (int64_t)ret * bs % kMod;return ret;
}inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }struct Vector {int a[kMaxK] = {0};friend Vector operator *(const Vector &b, const int w) {static Vector ret;for (int i = 1; i <= k; ++i) ret.a[i] = 1ll * w * b.a[i] % kMod;return ret;}friend Vector operator +(const Vector &a, const Vector &b) {static Vector ret;for (int i = 1; i <= k; ++i) ret.a[i] = add(a.a[i], b.a[i]);return ret;}
} f[kMaxN], bs[kMaxK];void prework() {std::queue<int> q;for (int i = 1; i <= n; ++i) {if (!deg[i]) q.emplace(i);if (i <= k) f[i].a[i] = 1;}for (; !q.empty();) {int u = q.front(); q.pop();for (auto [v, id] : G[u]) {f[v] = f[v] + f[u] * val[id];if (!--deg[v]) q.emplace(v);}}
}void ins(Vector a, int t) {for (int i = 1; i <= k; ++i) {if (a.a[i]) {if (t > tm[i]) std::swap(a, bs[i]), std::swap(t, tm[i]);int v = 1ll * a.a[i] * qpow(bs[i].a[i]) % kMod;a = a + bs[i] * sub(0, v);}}
}void dickdreamer() {std::cin >> n >> m >> k;for (int i = 1; i <= m; ++i) {int u, v;std::cin >> u >> v;G[u].emplace_back(v, i), ++deg[v], val[i] = rnd() % kMod;}prework();for (int i = k + 1; i <= n; ++i) {static int tt[kMaxK];ins(f[i], i);if (i > k) {for (int j = 1; j <= k; ++j) tt[j] = tm[j];tt[0] = i;std::sort(tt + 1, tt + 1 + k, std::greater<>());for (int j = 0; j <= k; ++j)if (tt[j]) res[j] += tt[j] - k;}}for (int i = 0; i < k; ++i) res[i] -= res[i + 1];for (int i = 0; i <= k; ++i) std::cout << res[i] << '\n';
}int32_t main() {
#ifdef ORZXKRfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifstd::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);int T = 1;// std::cin >> T;while (T--) dickdreamer();// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";return 0;
}
http://www.sczhlp.com/news/15595/

相关文章:

  • wordpress 页面显示分类文章列表整站seo怎么做
  • 那些网站可以做0首付分期手机百度导航如何设置公司地址
  • 动漫网站设计方案谷歌搜索引擎首页
  • 苏州市吴江区住房和城乡建设局网站百度客服人工电话95188
  • 网站开发设计项目书谷歌seo快速排名软件首页
  • 网站建设与管理读书心得腾讯企点官网
  • CF804B Minimum number of steps 题解
  • 一键入侵:Oracle云代码编辑器漏洞致用户面临远程代码执行风险
  • 面向多轮工具交互的强化学习策略优化技术
  • 25.8.18随笔联考总结
  • 个性化建网站定制仓山区seo引擎优化软件
  • 网站模板可以自己做网站平台有哪些
  • 枣阳网站建设 枣阳山水数码百度之家
  • 网站建设优惠活动营销网站建设
  • 网站上传在空间哪里广州企业网站seo
  • 沈阳公司做网站的聚名网官网登录
  • 店铺头像logo免费生成百度seo系统
  • html5网站建设公司代发qq群发广告推广
  • 学校网站建设哪家好软文是什么意思通俗点
  • 重庆网站建设公司海口凡科网免费建站
  • 0105_接口隔离原则
  • AtCoder [ABC339C] Perfect Bus 题解
  • luogu P9707 [KMOI R1] 音波武器 题解
  • 教育营销型的网站建设五种常用的网站推广方法
  • 网站用什么开发软件做关键词挖掘工具
  • 做携程网站的技术网页制作与设计
  • 网站开发最强工具今日重大事件
  • 长春做网站的公司哪家好四川seo哪里有
  • 做页面设计的网站在线推广
  • 模版网站后期可以更换图片吗武汉网站推广很 棒