//目录

Codeforces 396A 数论,组合数学

题意:给一个a数组,求b 数组的方案数,但是要求两者乘积相同。

 

分析:

不可能将它们乘起来,对于每个数质因数分解,得到每个质因子个数,遍历这些质因子,将某个质因子放到 对应的盒子里面,可以不放,方案数就是一个组合数,用插板法。

 

这里的素数板子挺好的,一方面可以用来判断,一方面存起来。

组合数,可以考虑用乘法逆元。

每个质因子个数hash一下。

#include <bits/stdc++.h>

using namespace std;

const int MOD = 1e9 + 7;
#define N 50009
typedef long long ll;

const int maxnn = 15000+5;
int C[maxnn][505];

void init() {
    memset(C, 0, sizeof(C));
    C[0][0] = 1;
    C[1][0] = C[1][1] = 1;
    for(int i = 2; i < maxnn; ++i)
    {
        C[i][0] = C[i][i] = 1;
        for(int j = 1; j < i; ++j)
        {
            C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
        }
    }
}

bool vis[50009];
int primes[50009];
int num_prime;
int get_primes (int m) {        //获取一定范围内的素数
    memset(vis,0,sizeof(vis));
    for(int i=2;i<m;i++) {
        if(!vis[i])
            primes[num_prime++]=i;
        for(int j=0;j<num_prime && i*primes[j]<m;j++)  {
            vis[i*primes[j]]=1;
            if(!(i%primes[j]))
                break;
        }
    }
    return num_prime;
}

std::map<int, int> mp;

void divide(int x) {
    int temp = (int)sqrt(x*1.0);
    for(int i=0;i<num_prime;i++) {
        if(primes[i]>temp) break;
        while(x%primes[i]==0) {
            mp[primes[i]]++;
            x /=primes[i];
        }
    }
    if(x!=1)
        mp[x]++;
}

int main(int argc, char const *argv[])
{
    mp.clear();
    init();
    get_primes(N);
    int n,x;
    scanf("%d",&n);
    for(int i=0;i<n;i++) {
        scanf("%d",&x);
        divide(x);
    }

    ll ans= 1;
    std::map<int, int> ::iterator p;

    for(p = mp.begin();p!=mp.end();p++) {
        int k = p->second;

        ans = ans * C[k+n-1][n-1] % MOD;
    }

    printf("%lld\n", ans);

    return 0;
}

 

posted @ 2017-07-28 22:01  小草的大树梦  阅读(246)  评论(0编辑  收藏  举报