社区讨论
论一种猎奇的O(n)求n!的方式
学术版参与者 21已保存回复 36
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 36 条
- 当前快照
- 1 份
- 快照标识符
- @mhjcw01g
- 此快照首次捕获于
- 2025/11/04 00:30 4 个月前
- 此快照最后确认于
- 2025/11/04 06:10 4 个月前
我们发现目前较为正常的求 的做法都是通过 递推或递归求出答案。
考虑如何变成小唐人,如果你有一双智障的眼睛可以发现,
我们分奇偶讨论,
当 为偶数时,上式与下面的式子等价。 当 为奇数时,上式与下面的式子等价。 注意到这和快速幂的形式是相似的。
考虑递归发现可以做到 求 。
当 为偶数时,上式与下面的式子等价。 当 为奇数时,上式与下面的式子等价。 注意到这和快速幂的形式是相似的。
考虑递归发现可以做到 求 。
但我们该如何求 ,我们可以采取递推的方法。
我们知道 , 那么将 我们就证明了这是可以 预处理的。
我们知道 , 那么将 我们就证明了这是可以 预处理的。
可是就算如此,对于每个 以快速幂的形式求 ,需要 ,但是显然,我们可以记忆化,最终时间复杂度 。
code
C#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,p=998244353;
int inv[N],ans[N],C[N];
void quick_pow(int x){
if(ans[x]!=0) return ;
if(x==1) return ;
quick_pow(x/2);
if(x&1) ans[x]=C[x]*ans[x/2]%p*ans[x/2]%p*(x+1)%p*inv[2]%p;
else ans[x]=C[x]*ans[x/2]%p*ans[x/2]%p;
return ;
}
signed main(){
int n;
cin >>n;
inv[1]=C[0]=C[1]=ans[1]=1;
for(int i=2;i<=n;i++){
inv[i]=p-(p/i)*inv[p%i]%p;
C[i]=C[i-1]*i%p*inv[(i+1)/2]%p;
}
for(int i=n;i>0;i--) quick_pow(i);
for(int i=1;i<=n;i++) cout <<ans[i]<<" ";
// cout <<ans[n];
return 0;
}
只输出
ans[n] 可以通过P5739。回复
共 36 条回复,欢迎继续交流。
正在加载回复...