首页 > 其他分享 >P5825 排列计数 加强版

P5825 排列计数 加强版

时间:2024-07-28 11:50:32浏览次数:13  
标签:非升段 加强版 int text poly 计数 P5825 res mod

加强版和原题不同之处在于 \(p\) 不再是一个排列,而是一个普通的值域为 \([1,n]\) 的数组

考虑将 \([p_i <p_{i+1}]\) 转化为 \(1-[p_i \ge p_{i+1}]\),方便计算后面的 \(g\),也就是恰好 \(n-k-1\) 不上升点的方案数

记一段不上升点的连续段为非升段,\(f_i\) 表示恰好 \(i\) 个不上升点的方案数,即将序列划分为 \(n-i\) 段非升段的方案数

由于恰好不好计算,考虑二项式反演,记 \(g_i\) 表示钦定 \(i\) 段非升段的方案数

那么 \(f_i=\sum\limits_{i=j}^{n-1} \tbinom{j}{i} (-1)^{j-i} g_{n-j}\)

由于只要确定了数集便能确定整个序列,那么相当于要把 \(p\) 划分为 \(n-i\) 个数集,可以枚举每一种数,然后直接把它们的方案数乘起来,但是这样可能会出现空集,那么再来容斥一下

记 \(h_i\) 表示钦定 \(i\) 段可为空集的非升段的方案数,那么 \(h_i=\prod\limits_{j=1}^n \tbinom{i+c_j-1}{i-1}\)(\(c_j\) 个球放入 \(i\) 个盒子),\(c\) 为每种数字的出现次数

那么 \(g_i=\sum\limits_{j=0}^i \tbinom{i}{j} (-1)^j h_{i-j}\),组合数是强制先选择 \(j\) 个空集

考虑快速计算 \(f,g,h\),可以发现 \(f,g\) 拆掉组合数之后,\(g\) 再反转一下就是标准的卷积,\(\text{ntt}\) 优化即可,而 \(h\) 可以发现本质不同的 \(c\) 只有 \(\text{O}(\sqrt n)\) 个,直接套一个快速幂即可,某位大佬表示算上快速幂这部分的复杂度还是 \(\text{O}(\sqrt n)\)

#include<bits/stdc++.h>
using namespace std;
#define poly vector<long long>
#define fix(f,n) f.resize(n+1)
#define c(n,m) (n<m||m<0||n<0?0:fac[n]*ifac[m]%mod*ifac[n-(m)]%mod)
int n,x,cnt[500001],num[500001],rev[3000001],w[3000001];
long long ans[500001],fac[1000001],ifac[1000001],inv[1000001];
const int mod=998244353;
auto qpow(long long a,long long b){
    long long res=1;
    for(;b;b>>=1,a=a*a%mod) if(b&1) res=res*a%mod;
    return res;
}
void init(int n,int m){
    fac[0]=ifac[0]=inv[1]=w[n]=1,w[n|1]=qpow(3,(mod-1)/n);
    for(int i=2;i<n;i++) w[n|i]=1ll*w[n|i-1]*w[n|1]%mod;
    for(int i=n-1;i>=1;i--) w[i]=w[i<<1];
    for(int i=2;i<=m;i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod;
    for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod,ifac[i]=ifac[i-1]*inv[i]%mod;
}
void ntt(poly &f,int c,int n){
    fix(f,n-1);
    for(int i=0;i<n;i++) if(i<rev[i]) swap(f[i],f[rev[i]]);
    for(int k=2;k<=n;k<<=1){
        for(int i=0;i<n;i+=k){
            for(int j=i,*p=w+k;j<i+(k>>1);j++){
                int x=f[j],y=f[j+(k>>1)]*(*p++)%mod;
                f[j+(k>>1)]=(x-y+mod)%mod;
                f[j]=(x+y)%mod;
            }
        }
    }
    if(!c) reverse(f.begin()+1,f.begin()+n);
}
poly operator*(poly f,poly g){
    int m=f.size()+g.size()-2,n=1<<__lg(m)+1,p=0;
    for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|(i&1?n>>1:0);
    ntt(f,1,n),ntt(g,1,n),p=qpow(n,mod-2);
    for(int i=0;i<n;i++) f[i]=f[i]*g[i]%mod;
    ntt(f,0,n),fix(f,m);
    for(int i=0;i<=m;i++) f[i]=f[i]*p%mod;
    return f;
}
int main(){
	scanf("%d",&n),init(1<<20,n*2);
    for(int i=1;i<=n;i++) scanf("%d",&x),cnt[x]++;
    poly s,k,f(n),g(n+1),h(n+1,1);
    h[0]=0;
    for(int i=1;i<=n;i++) if(cnt[i]) num[cnt[i]]++;
    for(int i=1;i<=n;i++) if(num[i]) s.push_back(i);
    for(int i=1;i<=n;i++) for(auto j:s) h[i]=h[i]*qpow(c(i+j-1,i-1),num[j])%mod;
    for(int i=0;i<=n;i++) g[i]=i&1?mod-ifac[i]:ifac[i],h[i]=h[i]*ifac[i]%mod;
    k=g*h,fix(g,n-1);
    for(int i=1;i<=n;i++) g[n-i]=k[i]*fac[i]%mod;
    for(int i=0;i<n;i++) f[n-1-i]=i&1?mod-ifac[i]:ifac[i];
    for(int i=0;i<n;i++) g[i]=g[i]*fac[i]%mod;
    f=f*g;
    for(int i=0;i<n;i++) ans[i]=ifac[i]*f[n-1+i]%mod;
    for(int i=0;i<n;i++) printf("%lld ",ans[n-i-1]);
	return 0;
}

标签:非升段,加强版,int,text,poly,计数,P5825,res,mod
From: https://www.cnblogs.com/zyxawa/p/18328055

相关文章

  • 在 Python 中读取部分 MP3 文件时处理“对于可用位计数来说太大”错误
    我正在尝试读取MP3文件的特定部分,但遇到错误:[src/libmpg123/layer3.c:INT123_do_layer3():1771]error:part2_3_length(1376)toolargeforavailablebitcount(760)可以访问音频文件此处我的环境是使用此Docker映像设置的:pytorc......
  • IOI2022 邮局 加强版 题解
    [IOI2000]邮局加强版题解考虑动态规划,设\(f_{i,j}\)为经过了\(i\)个村庄,正在建第\(j\)​个邮局的最优距离。以及\(w_{i,j}\)表示区间\([i,j]\)​内建一个邮局时的距离总和。\(a\)数组表示每个村庄的坐标编号。朴素版状态转移方程:\[f_{i,j}=\min(f_{i,j},f_{k,j......
  • P1989 无向图三元环计数
    原题链接题解暴力方法:遍历每个节点,遍历每个节点的子节点,遍历每个子节点的子节点,看看子子节点是否是节点的子节点,时间复杂度\(O(nm^2)\)优化考虑无向边建边的时候建成有向边,且两个点建边时,度数小的指向度数大的,如果度数相等,编号小的指向编号大的(其实这一步是为了避免重复计数......
  • 【MATLAB源码】机器视觉与图像识别技术(4)---模式识别与视觉计数
    系列文章目录第一篇文章:【MATLAB源码】机器视觉与图像识别技术—视觉系统的构成(视频与图像格式转换代码及软件下载)第二篇文章:【MATLAB源码】机器视觉与图像识别技术(2)—图像分割基础第三篇文章:【MATLAB源码】机器视觉与图像识别技术(2)续—图像分割算法第四篇文章:【MATL......
  • 按小计和计数对 Pandas 数据框进行排序
    我有一个非常大的数据集,名为bin_df。使用pandas和以下代码,我为每个组分配了小计“总计”:bin_df=df[df["category"].isin(model.BINARY_CATEGORY_VALUES)]bin_category_mime_type_count_df=(bin_df.groupby(["category","mime_type&quo......
  • 汉明权重(Hamming Weight)(统计数据中1的个数)VP-SWAR算法
    汉明权重(HammingWeight)(统计数据中1的个数)VP-SWAR算法定义汉明重量是一串符号中非零符号的个数。它等于同样长度的全零符号串的汉明距离(在信息论中,两个等长字符串之间的汉明距离等于两个字符串对应位置的不同字符的个数)。汉明重量在常见的数据位符号串中,它是1的个数。......
  • YC322A [ 20240724 CQYC NOIP 模拟赛 T4 ] 庫的 序计数(counting)
    题意给定一棵树\(T\),每次操作在某个点下方接上\(k\)个儿子。询问期望多少次排列,使得\(a_{fa_i}<a_i\)。保证\(k\)是偶数,对\(65536\)取模。\(n\le10^5,k\le2\times10^9\)。Sol考虑假如已经确定了一棵树的形态,如何求出最终的答案?可以发现对于每一个节点......
  • 计数调用装饰器 - 为什么我将函数属性重置回 0?
    下面的代码计算了装饰函数func被调用的次数:fromfunctoolsimportwrapsdefcounting_calls(func):@wraps(func)definner(*args,**kwargs):inner.call_count+=1returnfunc(*args,**kwargs)inner.call_count=0returninner......
  • 《埃尔登指环》死亡计数器
    我正在尝试制作自己的死亡计数器埃尔登戒指,我已经制作了一个手动计数应用程序,但我想自动化该过程,或者有一个脚本,如下面的站点,它将打开一个窗口,其中我还需要加载(A最好自动确定保存位置-并计算死亡人数);问题是:制作统计死亡人数的脚本的最佳方法是什么?读取游戏内存?但是我怎样才能......
  • 基于YOLOv8的汽车跟踪计数(创新点,功能实现保姆级教程)
    效果如视频所示:  YOLOV8github地址:GitHub-ultralytics/ultralytics:NEW-YOLOv8......