Solution -「NOI Simu.」逆天题
\(\mathscr{Description}\)
对于 \(r=0,1,\cdots,n-1\), 设 \(\{1,2,\cdots,nm\}\) 中有 \(f_r\) 个子集满足子集内元素之和 \(\bmod n=r\), 求出
\]
\(n,m\le10^{18}\).
\(\mathscr{Solution}\)
我们知道 \(f\) 的 GF:
\]
于是我们需要用 \(\omega_n\) 对 \(F\) 做 DFT. 不妨设 \(\hat{f_k}=\operatorname{DFT}(\boldsymbol f)_k\), 那么
\]
看过 3B1B 的视频, 我们已知了对乘积式 \(\prod_{i=0}^{n-1}(1+\omega_n^i)\) 的处理技巧:
注意到 \(1-z^n=0\Leftrightarrow z=\omega_n^k\), 那么 \(1-z^n=\prod_{i=0}^{n-1}(z-\omega_n^i)\). 代入 \(z=-1\), 观察左右, 我们有 \(\prod_{i=0}^{n-1}(1+\omega_n^i)=2[2\nmid n]\).
指标乘上常数 \(k\), 无非让 \(\omega_n\) 转圈圈的速度发生了一些变化. 令 \(d=\gcd(k,n)\), 容易得到
\]
答案应当为 \(\boldsymbol f^2\), 也即是 \(\sum_{i=0}^{n-1}f_i^2\). 注意到 \(\gcd(k,n)=\gcd(n-k,n)\), 于是 \(f_i=f_{n-i}\), 所以只需要求
\]
如果能算 \(\hat{\boldsymbol f}\), 我们就能立马得到 \(\operatorname{DFT}(F^2)\), 接下来只需要提取 IDFT 矩阵的第一行 (带上 \(\frac{1}{n}\) 的系数) 与 \(F^2\) 的 DFT 向量做点乘就能得到答案.
如何算 \(\hat{\boldsymbol f}\)? 将 \(n\) 素因数分解, 暴力枚举 \(d\) 算贡献即可. 使用 Pollard-Rho, 动态维护 \(\varphi(n/d)\), 预处理 \(2\) 的光速幂, 可以做到 \(\mathcal O(\sqrt P+Td(n))\), 其中 \(P=998244353\), \(d(n)\) 为 \(n\) 的因子个数 (其自然比 Pollard-Rho 的 \(n^{1/4}\) 高阶).
\(\mathscr{Code}\)
/*+Rainybunny+*/
// #include <bits/stdc++.h>
#include <bits/extc++.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)
typedef long long LL;
#define fi first
#define se second
const int MOD = 998244353;
LL n, m;
__gnu_pbds::gp_hash_table<LL, int> fct;
namespace Factor {
inline LL add(LL u, const LL v, const LL m) {
return (u += v) < m ? u : u - m;
}
inline LL mul(const LL u, const LL v, const LL m) {
return __int128(u) * v % m;
}
inline LL mpow(LL u, LL v, LL m) {
LL ret = 1;
for (; v; u = mul(u, u, m), v >>= 1) ret = mul(ret, v & 1 ? u : 1, m);
return ret;
}
inline LL gcd(const LL u, const LL v) { return v ? gcd(v, u % v) : u; }
inline LL labs(const LL u) { return u < 0 ? -u : u; }
inline bool millerRabin(const LL x, const LL b) {
LL k = x - 1; while (!(k & 1)) k >>= 1;
static LL pwr[70]; pwr[0] = 1, pwr[1] = mpow(b, k, x);
while (k != x - 1) {
pwr[pwr[0] + 1] = mul(pwr[pwr[0]], pwr[pwr[0]], x);
++pwr[0], k <<= 1;
}
per (i, pwr[0], 1) {
if (pwr[i] != 1 && pwr[i] != x - 1) return false;
if (pwr[i] == x - 1) return true;
}
return true;
}
inline bool isprime(const LL x) {
if (x == 2 || x == 3 || x == 5 || x == 7 || x == 11) return true;
if (x == 61 || x == 127) return true;
if (!(x % 2) || !(x % 3) || !(x % 5) || !(x % 7) || !(x % 11))return false;
if (!(x % 61) || !(x % 127)) return false;
return millerRabin(x, 2) && millerRabin(x, 61) && millerRabin(x, 127);
}
inline LL pollardRho(const LL x) {
static std::mt19937 emt(time(0) ^ 20120712);
for (LL a = emt() % (x - 1) + 1, len = 1, st = 0, ed = 0; ;
len <<= 1, st = ed) {
LL prd = 1;
rep (stp, 1, len) {
prd = mul(prd, labs(st - (ed = add(mul(ed, ed, x), a, x))), x);
if (!(stp & 127) && gcd(prd, x) > 1) return gcd(prd, x);
}
if (gcd(prd, x) > 1) return gcd(prd, x);
}
}
inline void factor(LL x, __gnu_pbds::gp_hash_table<LL, int>& res,
const int k = 1) {
if (x == 1) return ;
if (isprime(x)) return void(res[x] += k);
LL d = pollardRho(x); int cnt = 0;
while (!(x % d)) x /= d, ++cnt;
factor(x, res, k), factor(d, res, k * cnt);
}
} // namespace Factor
inline int mul(const int u, const int v) { return 1ll * u * v % MOD; }
inline void addeq(int& u, const int v) { (u += v) >= MOD && (u -= MOD); }
inline int mpow(int u, int v) {
int ret = 1;
for (; v; u = mul(u, u), v >>= 1) ret = mul(ret, v & 1 ? u : 1);
return ret;
}
namespace Power2 {
const int SM = 31596;
int sma[SM + 1], gnt[SM + 1];
inline void init() {
sma[0] = 1;
rep (i, 1, SM) addeq(sma[i] = sma[i - 1], sma[i - 1]);
gnt[0] = 1, gnt[1] = sma[SM];
rep (i, 2, SM) gnt[i] = mul(gnt[i - 1], gnt[1]);
}
inline int power(const int u) {
return mul(sma[u % SM], gnt[u / SM]);
}
} // namespace Power2
inline int calc(const __gnu_pbds::gp_hash_table<LL, int>
::iterator&& it, LL d, LL phi) {
if (it == fct.end()) {
return mul(phi % MOD, Power2::power(2 * d % (MOD - 1)
* (m % (MOD - 1)) % (MOD - 1)));
}
int ret = 0;
rep (i, 0, it->se) {
if (i == repi || it->fi != 2) addeq(ret, calc(std::next(it), d, phi));
if (i == repi) break;
d *= it->fi, phi /= it->fi - (i + 1 == repi);
}
return ret;
}
int main() {
freopen("ntt.in", "r", stdin);
freopen("ntt.out", "w", stdout);
Power2::init();
int T; scanf("%d", &T);
while (T--) {
scanf("%lld %lld", &n, &m);
fct.clear(), Factor::factor(n, fct);
LL phi = n;
for (const auto& p: fct) phi = phi / p.fi * (p.fi - 1);
printf("%d\n", mul(mpow(n % MOD, MOD - 2), calc(fct.begin(), 1, phi)));
}
return 0;
}
Solution -「NOI Simu.」逆天题的更多相关文章
- Solution -「基环树」做题记录
写的大多只是思路,比较简单的细节和证明过程就不放了,有需者自取. 基环树简介 简单说一说基环树吧.由名字扩展可得这是一类以环为基础的树(当然显然它不是树. 通常的表现形式是一棵树再加一条非树边,把图画 ...
- Solution -「NOI 2021」「洛谷 P7740」机器人游戏
\(\mathcal{Description}\) Link. 自己去读题面叭~ \(\mathcal{Solution}\) 首先,参悟[样例解释 #2].一种暴力的思路即为钦定集合 \ ...
- Solution -「NOI 2020」「洛谷 P6776」超现实树
\(\mathcal{Description}\) Link. 对于非空二叉树 \(T\),定义 \(\operatorname{grow}(T)\) 为所有能通过若干次"替换 \( ...
- Solution -「NOI 2016」「洛谷 P1587」循环之美
\(\mathcal{Description}\) Link. 给定 \(n,m,k\),求 \(x\in [1,n]\cap\mathbb N,y\in [1,m]\cap \mathbb ...
- Solution -「NOI 2012」「洛谷 P2050」美食节
\(\mathcal{Description}\) Link. 美食节提供 \(n\) 种菜品,第 \(i\) 种的需求量是 \(p_i\),菜品由 \(m\) 个厨师负责制作,第 \(j\) ...
- Solution -「NOI 2008」「洛谷 P3980」志愿者招募
\(\mathcal{Description}\) Link. 一项持续 \(n\) 天的任务,第 \(i\) 天需要至少 \(a_i\) 人工作.还有 \(m\) 种雇佣方式,第 \(i\) ...
- Solution -「NOI 2018」「洛谷 P4768」归程
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向连通图,边形如 \((u,v,l,a)\).每次询问给出 \(u,p\),回答 ...
- Solution -「ARC 104E」Random LIS
\(\mathcal{Description}\) Link. 给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...
- Solution -「NOI 模拟赛」出题人
\(\mathcal{Description}\) 给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\ ...
- Solution -「NOI.AC 省选膜你赛」union
题目 题意简述 给定两颗树 \(A,B\),\(A\) 中的任一结点 \(u\) 与 \(B\) 中的任一结点 \(v\) 都有一个关系值 \(f(u,v)\),初始为 \(0\).再给出 \(q ...
随机推荐
- Flink CDC 与Hudi整合
介绍 之前写过Flink CDC sink 到 Iceberg中,本篇主要实践如何CDC到hudi中. 什么是hudi? Hudi is a rich platform to build stream ...
- 2.15 Linux中一切皆文件[包含优缺点]
Linux 中所有内容都是以文件的形式保存和管理的,即一切皆文件,普通文件是文件,目录(Windows 下称为文件夹)是文件,硬件设备(键盘.监视器.硬盘.打印机)是文件,就连套接字(socket). ...
- apache2和nginx卸载总是不干净不完全导致无法重装,重装成功也无法启动
大着胆子把nginx卸载了用的命令是 sudo apt remove nginx 结果最后不知道怎么折腾的就算重新装也装不上了,然后就转头折腾apache2,也卸载了 sudo apt remov ...
- 70 个群都来问我的 AI 日报,是这么做的。
最近我给 FastGPT 用户交流群里接入了 AI 日报,每天早上 10 点会自动向群里推送 AI 日报,让群里的小伙伴们第一时间了解到昨天 AI 领域都发生了哪些大事. 效果大概是这个样子的: 如果 ...
- Custom PMD Rules
by Tom Copeland04/09/2003 A Review of PMD A few weeks ago, O'Reilly Network ran an article on PMD, a ...
- 基本ROP
ret2text [NewStarCTF 2023 公开赛道]ret2text (64) execve本身并不是一个后门函数. 实际上,execve是一个标准的系统调用函数,用于在 Linux和类 U ...
- MySQL 8.0 为什么会放弃查询缓存?
什么是查询缓存? 查询缓存就是将一次查询结果存储在内存中,假如下一次查询结果在内存中,就直接在内存中读取. 设计初衷 当然是提高性能,通过缓存来减少解析器.优化器.存储引擎的执行时间. MySQL查询 ...
- 利用 Databend + COS助力 CDH 分析 | 某医药集团
作者: 黄志武 某医药集团信息中心数据库组组长,13 年数据库行业从业经历,Oracle OCM,关注 Oracle.MySQL.Redis.MongoDB.Oceanbase.Tidb.Polard ...
- 百度地图各种控件:地图平移缩放控件NavigationControl、地图类型控件MapTypeControl
注:代码复制即可用,标色代码为主要代码 百度地图提供了如下控件: 1.Control:控件的抽象基类,所有控件均继承此类的方法.属性.通过此类您可实现自定义控件. 2.NavigationContro ...
- Flutter GestureDector点击空白区域不响应
GestureDector点击空白区域不响应 当GestureDector嵌套Container时,当Container子组件为Text时,点击空白区域不响应点击事件 GestureDetector( ...