P9007 [入门赛 #9] 最澄澈的空与海 (Hard Version) 题解
Upd on 2023.10.14 08:21:修改了推式子和题意的一些小错误。
前言
一道恐怖的绿题。显然我认为应该是蓝题。(不过在这篇题解写到一半的时候升蓝了,感谢 @StudyingFather。)
名字挺好的。
题意
给定
-
。 -
且 。 -
。
答案为 inf
。
多组数据。
解法
首先我们需要将式子变形。最开始,将两式相减,得到:
然后继续化简:
可以发现
考虑
于是这道题就转化为了求
根据约数个数定理和唯一分解定理,设
设
不过显然这样质因数分解很慢,考虑优化。
首先考虑线性筛的本质。在线性筛的过程中,每个合数都只会被它最小的质因数标记。考虑把它存下来,这样质因数分解的复杂度就降到了
考虑继续优化上面的过程。
由于增加了多测,那么我们可以换一种方式,不一定要在线求答案,考虑预处理。
设
设
由于
最后处理一个特殊情况,前文我们都只考虑了
那么
那么这时候,inf
即可。
毒瘤。
AC Code
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 1e6 + 5, Mod = 998244353; int t, n, Ans[N], dp[N], pri[N], fac[N], inv[N]; vector<int> prime; vector< pair<int, int> > f; bool vis[N]; void Prime(int x) { vis[1] = true; for(int i = 2; i <= x; i++) { if(!vis[i]) prime.push_back(i), pri[i] = i; for(auto p : prime) { if(i * p > x) break; vis[i * p] = true; pri[i * p] = p; if(!(i % p)) break; } } return; } void p_fac(int x) { f.clear(); while(x != 1) { int y = pri[x], cnt = 0; while(!(x % y)) x /= y, cnt++; f.push_back(make_pair(y, cnt)); } return; } void Inv(int x) { inv[1] = 1; for(int i = 2; i <= x; i++) inv[i] = (Mod - Mod / i) * inv[Mod % i] % Mod; return; } void init(int n) { Prime(1e6); Inv(1e6); int ans = Ans[0] = 1; for(int i = 1; i <= n; i++) { p_fac(i); for(auto j : f) { int p = j.first, num = j.second; ans = ans * inv[dp[p] + 1] % Mod; dp[p] += num * 2; ans = ans * (dp[p] + 1) % Mod; } Ans[i] = ans; for(auto j : f) { int p = j.first, num = j.second; // cout << ans << " " << inv[dp[p] + 1] << " " << dp[p] + 1 << " "; ans = ans * inv[dp[p] + 1] % Mod; dp[p] -= num; ans = ans * (dp[p] + 1) % Mod; } } return; } signed main() { init(1e6); cin >> t; while(t--) { cin >> n; cout << (n == 1 ? "inf" : to_string(Ans[n - 1])) << "\n"; } return 0; }
本文作者:Luckies
本文链接:https://www.cnblogs.com/Luckies/p/17962648/P9007
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步