首页 > 其他分享 >D. Counting Factorizations

D. Counting Factorizations

时间:2023-11-13 20:13:48浏览次数:36  
标签:prime int 质数 Factorizations 2n Counting ldots mod

D. Counting Factorizations

The prime factorization of a positive integer $m$ is the unique way to write it as $\displaystyle m=p_1^{e_1}\cdot p_2^{e_2}\cdot \ldots \cdot p_k^{e_k}$, where $p_1, p_2, \ldots, p_k$ are prime numbers, $p_1 < p_2 < \ldots < p_k$ and $e_1, e_2, \ldots, e_k$ are positive integers.

For each positive integer $m$, $f(m)$ is defined as the multiset of all numbers in its prime factorization, that is $f(m)=\{p_1,e_1,p_2,e_2,\ldots,p_k,e_k\}$.

For example, $f(24)=\{2,3,3,1\}$, $f(5)=\{1,5\}$ and $f(1)=\{\}$.

You are given a list consisting of $2n$ integers $a_1, a_2, \ldots, a_{2n}$. Count how many positive integers $m$ satisfy that $f(m)=\{a_1, a_2, \ldots, a_{2n}\}$. Since this value may be large, print it modulo $998\,244\,353$.

Input

The first line contains one integer $n$ ($1\le n \le 2022$).

The second line contains $2n$ integers $a_1, a_2, \ldots, a_{2n}$ ($1\le a_i\le 10^6$)  — the given list.

Output

Print one integer, the number of positive integers $m$ satisfying $f(m)=\{a_1, a_2, \ldots, a_{2n}\}$ modulo $998\,244\,353$.

Examples

input

2
1 3 2 3

output

2

input

2
2 2 3 5

output

5

input

1
1 4

output

0

Note

In the first sample, the two values of $m$ such that $f(m)=\{1,2,3,3\}$ are $m=24$ and $m=54$. Their prime factorizations are $24=2^3\cdot 3^1$ and $54=2^1\cdot 3^3$.

In the second sample, the five values of $m$ such that $f(m)=\{2,2,3,5\}$ are $200, 225, 288, 500$ and $972$.

In the third sample, there is no value of $m$ such that $f(m)=\{1,4\}$. Neither $1^4$ nor $4^1$ are prime factorizations because $1$ and $4$ are not primes.

 

解题思路

  对于合法的 $f(m)=\{a_1, a_2, \ldots, a_{2n}\}$,$a_1, a_3, \ldots, a_{2n-1}$ 相当于 $m$ 质因数分解后的 $n$ 项底数,要求是 $n$ 个互不相同且递增的质数。剩下的 $a_2, a_4, \ldots, a_{2n}$ 则是对应项的指数,可以是任意数。因此在初始的 $2n$ 个元素中,如果互不相同的质数的数量小于 $n$,那么就不存在合法方案,答案为 $0$。

  定义 $b_x$ 表示合数 $x$ 的出现次数,假设有 $s$ 个不同的合数。$c_x$ 表示质数 $x$ 的出现,假设有 $t$ 个不同的质数。当从 $t$ 个不同质数中选择了 $n$ 个作为底数,用 $c'_x$ 表示每个质数剩余的个数,其中如果选择了 $x$,则 $c'_x = c_x - 1$ 否则 $c'_x = c_x$。当确定了底数的选择后,那么合法的 $m$ 的数量就取决于剩余的 $n$ 个数能组成不同的指数方案,即$$\frac{n!}{b_1!\:\:b_2!\ldots b_s!\:\:c'_1!\:\:c'_2!\ldots c'_t!}$$

  考虑所有可能的底数选择方案,那么最终答案就是各个方案所对应的上式的和。

  注意到每个对于求和的每一项中,$\dfrac{n!}{b_1!\:\:b_2!\ldots b_s!}$ 都是一样的,因此只需求每一项的 $\dfrac{1}{c'_1!\:\:c'_2!\ldots c'_t!}$ 的和,最后乘上 $\dfrac{n!}{b_1!\:\:b_2!\ldots b_s!}$ 即可。

  由于在选择底数的方案中,第 $i$ 个质数可选可不选,因此可以 01 背包来求所有方案的 $\dfrac{1}{c'_1!\:\:c'_2!\ldots c'_t!}$ 的总和。定义 $f(i,j)$ 表示从前 $i$ 个质数中选出了 $j$ 个的所有方案对应项的总和。假设第 $i$ 个质数是 $x$,状态转移方程为$$f(i,j) = f(i-1,j) \times \frac{1}{c_x!} + f(i-1,j-1) \times \frac{1}{(c_x - 1)!}$$

  那么所有可能的底数选择方案对应的 $\dfrac{1}{c'_1!\:\:c'_2!\ldots c'_t!}$ 的总和就是 $f(t,n)$,最终答案就是 $\dfrac{n!}{b_1!\:\:b_2!\ldots b_s!} \times f(t,n)$。

  由于涉及到出除法,可以先通过 $O(n \log {(\text{mod})})$ 的复杂度预处理出所有阶乘的乘法逆元,在状态转移时只需乘上阶乘的乘法逆元即可。

  AC 代码如下,时间复杂度为 $O(n \log ({\text{mod}}) + n^2)$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 4100, M = 1e6 + 10, mod = 998244353;

int a[N], c[M];
int primes[M], cnt;
bool vis[M];
int infact[N];
int f[N];

void get_prime(int n) {
    for (int i = 2; i <= n; i++) {
        if (!vis[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] * i <= n; j++) {
            vis[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int qmi(int a, int k) {
    int ret = 1;
    while (k) {
        if (k & 1) ret = 1ll * ret * a % mod;
        a = 1ll * a * a % mod;
        k >>= 1;
    }
    return ret;
}

int main() {
    int n;
    scanf("%d", &n);
    infact[0] = 1;
    for (int i = 1; i <= n << 1; i++) {
        scanf("%d", a + i);
        c[a[i]]++;    // 统计每个元素的出现次数
        infact[i] = 1ll * infact[i - 1] * qmi(i, mod - 2) % mod;    // 计算阶乘i!的逆元 
    }
    int ret = 1;
    for (int i = 1; i <= n; i++) {    // 计算n!
        ret = 1ll * ret * i % mod;
    }
    get_prime(M - 1);
    vis[1] = true;
    vector<int> p;
    for (int i = 1; i < M; i++) {
        if (c[i]) {
            if (vis[i]) ret = 1ll * ret * infact[c[i]] % mod;    // 合数则直接乘上阶乘的逆元
            else p.push_back(i);    // 把质数找出来
        }
    }
    f[0] = 1;
    for (auto &x : p) {
        for (int j = n; j >= 0; j--) {    // 01背包的优化写法
            f[j] = 1ll * f[j] * infact[c[x]] % mod;
            f[j] = (f[j] + 1ll * f[j - 1] * infact[c[x] - 1]) % mod;
        }
    }
    ret = 1ll * ret * f[n] % mod;    // 把质数部分的逆元乘上
    printf("%d", ret);
    
    return 0;
}

 

参考资料

  Codeforces Round 856 (Div. 2) Editorial:https://codeforces.com/blog/entry/113500

标签:prime,int,质数,Factorizations,2n,Counting,ldots,mod
From: https://www.cnblogs.com/onlyblues/p/17830021.html

相关文章

  • 剖析网络测量:Counting and Measuring Network Traffic
    全文共18000字,讲解了网络测量和计数中的多方面知识:网络测量的意义、网络测量的手段分类、网络测量在实现上的挑战、以及解决这些挑战所用到的技术和协同方案等等。参考书籍有:《NetworkAlgorithmics:AnInterdisciplinaryApproachtoDesigningFastNetworkedDevices(2ndE......
  • 题解 LOJ3483【[USACO21FEB] Counting Graphs P】
    题解P7418【[USACO21FEB]CountingGraphsP】problemBessie有一个连通无向图\(G\)。\(G\)有\(N\)个编号为\(1\ldotsN\)的结点,以及\(M\)条边(\(1\leN\le10^2,N-1\leM\le\frac{N^2+N}{2}\))。\(G\)有可能包含自环(一个结点连到自身的边),但不包含重边(连接同一对结点......
  • UVA1485 Permutation Counting
    传送门description一个长度为\(n\)的排列\(a\),其权值为满足\(a_i>i\)的位置的数量。求权值恰为\(k\)的长度为\(n\)的排列的方案数。\(n,k\leq1000\)solution设\(f_{i,j}\)表示考虑前\(i\)个数,钦定\(j\)个满足\(a_i>i\),这\(j\)个数排列的方案数。有转移......
  • PAT_A1049 Counting Ones【困难】
    Thetaskissimple:givenanypositiveinteger N,youaresupposedtocountthetotalnumberof1'sinthedecimalformoftheintegersfrom1to N.Forexample,given N being12,therearefive1'sin1,10,11,and12.InputSpecification:Eac......
  • SP13015 CNTPRIME -Counting Primes
    \(CNTPRIME\)-\(Counting\)\(Primes\)题目描述给定初始序列\(A\),然后对原序列有以下操作:操作\(1\):0lrv将区间\([l,r]\)全赋值为\(v\)。操作\(2\):1lr查询区间\([l,r]\)注意:多组测试和特殊的输出。题目分析:就是一道板子题,首先我们先用欧拉筛筛出值域\([2,10^6]\)内的......
  • [USACO17JAN] Promotion Counting P 题解
    [USACO17JAN]PromotionCountingP题解前言好久没写题解了,今天趁我心情好赶紧水一篇。思路首先拿到这题,关键词检索:子树,比\(p_i\)大的,树状数组!现在考虑如何去掉其他子树的贡献……emm,我直接在算贡献的时候去掉其他子树的贡献不就好了!当然,暴力去贡献复杂度肯定爆炸,这里考虑......
  • G. Counting Graphs
    G.CountingGraphs题意:添加几条线段,使得图仍保持原先的最小生成树通过画图我们发现,要添加u->v的线段,线段必须大于u->v的路径内的最大值,不然会破坏原先的最小生成树。那么该怎么维护路径内的最大值呢?方法:1.我们对边的大小进行排序,这样当前边一定大于等于之前的边,只要对当前边......
  • AtCoder Beginner Contest 288 Ex A Nameless Counting Problem
    洛谷传送门AtCoder传送门考虑到规定单调不降比较难搞。先设\(g_t\)为长度为\(t\)的满足条件的序列个数(可重且有顺序)。求这个可以设个dp,\(f_{d,i}\)表示考虑到从高到低第\(d\)位,当前\(t\)个数中有\(i\)个仍然顶上界,并且之前的位都满足异或分别等于\(X\)的限制。......
  • 挑战程序设计竞赛 2.1章习题 POJ 2386 Lake Counting
    https://vjudge.net/problem/POJ-2386由于最近的降雨,水在农夫约翰的田地上聚集,在这片田地中,每个方块都被表示为一个NxM(1≤N≤100;1≤M≤100)的矩形。每个方块可以是水('W')或干地('.')。农夫约翰想弄清楚他的田地上形成了多少个池塘。池塘是由含有水的相连方块组成的集合,......
  • counting题解
    \(N,M\le1e7\)接着反射容斥,考虑这道题怎么做如果去枚举不动步数,加上反射容斥,直接T飞了把-1/0/1操作转换一下,就成了0/1/2如果没有限制(不能<0或>m),n步方案就是\((1+x+x^2)^n\)设\(H=1+x+x^2\quadF=H^n\)那么对两边求导:\[nH^{n-1}H'=F'\]\[F'H=nFH'\]我们知道\[H=1+x+x^2......