codeforces 396A A. On Number of Decompositions into Multipliers(组合数学+数论)

来源:互联网 发布:日本人生活方式 知乎 编辑:程序博客网 时间:2024/05/29 04:58

题目链接:

codeforces 396A


题目大意:

给出n个数的序列,求取和这个序列的积相同但是序列本身不同的个数。


题目分析:

  • 组合数学的问题,对于每一个数我们可以将它分解质因数,然后统计整个序列的各个质因数的个数。
  • 那么符合要求的序列一定用这些质因数(每个质因数的个数保持不变)组成的,所以我们可以利用组合数学中的插板法,对每个质因数进行划分,划分给n个数(存在一些数没有分到的情况),那么就是Cn1+n1
  • 根据乘法原则,总的方案数就是每个质因数的划分数之积。

AC代码:

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <map>#define MAX 30007using namespace std;typedef long long LL;typedef map<int,LL> MIL;const LL mod = 1e9+7;LL fac[MAX],recFac[MAX];int n,a[MAX],mark[100007];MIL mp;LL inv ( LL num , LL x ){    LL ret = 1;    while ( x )    {        if ( x&1 )        {            ret *= num;            ret %= mod;        }        num *= num;        num %= mod;        x >>= 1;    }    return ret;}void init ( ){    fac[0] = 1;    for ( LL i = 1 ; i < MAX ; i++ )    {        fac[i] = fac[i-1]*i;        fac[i] %= mod;        recFac[i] = inv ( fac[i] , mod-2 );    }    memset ( mark , 0 , sizeof ( mark ) );    mark[1] = mark[0] = 1;    for ( int i = 2 ; i*i < MAX; i++ )    {        if ( mark[i] ) continue;        for ( int j =i*i ; j < MAX ; j += i )            mark[j] = 1;    }}void handle ( int num ){    for ( int i = 2 ; i*i <= num ; i++ )    {        if ( num%i ) continue;        if ( mark[i] ) continue;        while ( num%i == 0 )        {            num /= i;            mp[i]++;        }    }    if ( num > 1 ) mp[num]++;}LL C ( int n , int m ){    if ( m == 0 ) return 1;    return fac[n]*recFac[n-m]%mod*recFac[m]%mod;}int main ( ){    init ( );    while ( ~scanf ( "%d" , &n ) )    {        mp.clear();        for ( int i = 0 ; i < n ; i++ )        {            scanf ( "%d" , &a[i] );            handle ( a[i] );        }        LL ans = 1;        MIL::iterator it = mp.begin();        for ( ; it != mp.end() ; it++ )        {            int x = it->second;            ans *= C ( x+n-1 , n-1 );            ans %= mod;        }        printf ( "%lld\n" , ans );    }}
0 0