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

题目链接:

codeforces 396A


题目大意:

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


题目分析:

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

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define MAX 30007

using 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 );
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-08 13:29:36

codeforces 396A A. On Number of Decompositions into Multipliers(组合数学+数论)的相关文章

Codeforces 464C Substitutes in Number(高效+快速幂)

题目链接:Codeforces 464C Substitutes in Number 题目大意:给定一个字符串,以及n中变换操作,将一个数字变成一个字符串,可能为空串,然后最后将字符串当成一 个数,取模1e9+7. 解题思路:将操作倒过来处理,这样维护每个数来的val,len两个,val表示对应数值取模1e9+7,len表示对应有多少 位,再计算的过程中要使用. #include <cstdio> #include <cstring> #include <vector>

Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS

G. Xor-matic Number of the Graph http://codeforces.com/problemset/problem/724/G 题意:给你一张无向图.定义一个无序三元组(u,v,s)表示u到v的(不一定为简单路径)路径上xor值为s.求出这张无向图所有不重复三元组的s之和.1≤n≤10^5,1≤m≤2*10^5. 想法: 如果做过[Wc2011 xor]这道题目(题解),那么问题变得简单起来了. ①假设我们钦定一个(u,v),设任意一条u->v的路径xor值为X,

dp --- Codeforces 245H :Queries for Number of Palindromes

Queries for Number of Palindromes Problem's Link:   http://codeforces.com/problemset/problem/245/H Mean: 给你一个字符串,然后q个询问:从i到j这段字符串中存在多少个回文串. analyse: dp[i][j]表示i~j这段的回文串数. 首先判断i~j是否为回文,是则dp[i][j]=1,否则dp[i][j]=0; 那么dp[i][j]=dp[i][j]+dp[i][j-1]+dp[i+1[j

CodeForces 396A 数论 组合数学

题目:http://codeforces.com/contest/396/problem/A 好久没做数论的东西了,一个获取素数的预处理跟素因子分解写错了,哭瞎了,呵呵, 首先ai最大值为10^9,n为500,最坏的情况 m最大值为500个10^9相乘,肯定不能获取m了,首选每一个ai肯定是m的一个因子,然后能分解就把ai给分解素因子,这样全部的ai都分解了  就能得到m的 所有素因子 以及 所有素因子的个数,题目求的 是n个因子的 不同序列的个数,所以每次 只能选出n个因子,这n个因子由素因子

Codeforces 245H Queries for Number of Palindromes:区间dp

题目链接:http://codeforces.com/problemset/problem/245/H 题意: 给你一个字符串s. 然后有t个询问,每个询问给出x,y,问你区间[x,y]中的回文子串的个数. 题解: 表示状态: dp[x][y] = numbers 表示区间[x,y]中的回文子串个数. 找出答案: 每次询问:ans = dp[x][y] 如何转移: dp[x][y] = dp[x][y-1] + dp[x+1][y] - dp[x+1][y-1] + pal[x][y] 用到了容

CodeForces - 393E Yet Another Number Sequence

Discription Everyone knows what the Fibonacci sequence is. This sequence can be defined by the recurrence relation: F1?=?1,?F2?=?2,?Fi?=?Fi?-?1?+?Fi?-?2 (i?>?2). We'll define a new number sequence Ai(k) by the formula: Ai(k)?=?Fi?×?ik (i?≥?1). In thi

Codeforces 396A 数论,组合数学

题意:给一个a数组,求b 数组的方案数,但是要求两者乘积相同. 分析: 不可能将它们乘起来,对于每个数质因数分解,得到每个质因子个数,遍历这些质因子,将某个质因子放到 对应的盒子里面,可以不放,方案数就是一个组合数,用插板法. 这里的素数板子挺好的,一方面可以用来判断,一方面存起来. 组合数,可以考虑用乘法逆元. 每个质因子个数hash一下. #include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; #defi

Codeforces 464C Substitutes in Number 同余定理+模拟

题目链接:点击打开链接 题意: 给定一串数字 下面有n个操作 每行格式形如 d->t d为一位数字,t为任意长度的数字. t的长度和不超过100000 问:最后的结果%1e9+7 思路: 首先我们可以得到一个结论: 同余定理使用后不能再修改数字. 那么为了让同余定理能够使用,我们倒序处理每个数字,这样就能保证能够使用同余定理. 记录每个数字实际代表的数字和实际对应的位数. 然后倒序处理上来即可. #include <stdio.h> #include <string.h> #

Codeforces 546D Soldier and Number Game(数论)

类似筛素数的方法--求出前缀和.然后直接O(1)回答即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 6 7 const int N = 10000000 + 10; 8 9 int num[N]; 10 bool p[N]; 11 int T, n, m; 12 13 int main(){ 14 15 memset(p,