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;
}
时间: 2024-11-03 22:23:53

Codeforces 396A 数论,组合数学的相关文章

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 396A A. On Number of Decompositions into Multipliers(组合数学+数论)

题目链接: codeforces 396A 题目大意: 给出n个数的序列,求取和这个序列的积相同但是序列本身不同的个数. 题目分析: 组合数学的问题,对于每一个数我们可以将它分解质因数,然后统计整个序列的各个质因数的个数. 那么符合要求的序列一定用这些质因数(每个质因数的个数保持不变)组成的,所以我们可以利用组合数学中的插板法,对每个质因数进行划分,划分给n个数(存在一些数没有分到的情况),那么就是Cn?1质因数个数+n?1. 根据乘法原则,总的方案数就是每个质因数的划分数之积. AC代码: #

Codeforces 223APartial Sums 数论+组合数学

题意很简单,求不是那么好求的,k很大 要操作很多次,所以不可能直接来的,印象中解决操作比较多无非线段树 循环节 矩阵 组合数等等吧,这道题目 也就只能多画画什么 的了 就以第一个案例为主吧 , 3 1 2 3 k我们依据画的次数来自己定好了 下面的每个数表示这个位置的 数由最初的 数组num[]中多少个数加起来得到的 当k为0的时候呢,就是 1 1 1 k为1的时候呢 1 2 3 k为2的时候呢 1 3 6 那么k为3的时候 1 4 10 这里看一下 从数组下标0开始,那么其实就是 C(i +

Trailing Loves (or L&#39;oeufs?) CodeForces - 1114C (数论)

大意: 求n!在b进制下末尾0的个数 等价于求n!中有多少因子b, 素数分解一下, 再对求出所有素数的最小因子数就好了 ll n, b; vector<pli> A, res; void factor(ll x) { int mx = sqrt(x+0.5); REP(i,2,mx) if (x%i==0) { int t = 0; while (x%i==0) x/=i,++t; A.pb(pli(i,t)); } if (x>1) A.pb(pli(x,1)); } int main

CodeForces 300C --数论

A - A Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 300C Description Vitaly is a very weird man. He's got two favorite digits a and b. Vitaly calls a positive integer good, if the deci

数论 - 组合数学 --- 1的个数

1的个数 Mean: 输入一个n,计算小于10^n的正整数中含有1的数的个数. analyse: 这题是一道组合数学课后思考题. 基本思路:  组合数学乘法原则 + 容斥原理 n位数中,每位可选:{0,1,2,3,4,5,6,7,8,9},所以共有10^n种,其中要除掉每位都为0的情况,所以要减一. 其中每位上不选1的情况为:{0,2,3,4,5,6,7,8,9},所以共有9^n中,同样要除掉全部为0的情况. Time complexity:O(n) Source code: //Memory

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem F (Codeforces 831F) - 数论 - 暴力

Vladimir wants to modernize partitions in his office. To make the office more comfortable he decided to remove a partition and plant several bamboos in a row. He thinks it would be nice if there are n bamboos in a row, and the i-th from the left is a

CodeForces 359D (数论+二分+ST算法)

题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319 题目大意:给定一个序列,要求确定一个子序列,①使得该子序列中所有值都能被其中一个值整除,②且子序列范围尽可能大(r-l尽可能大). 解题思路: 对于要求1,不难发现只有min(L,R)=gcd(L,R)时才行.其中gcd是L,R范围内的最大公约数,min是L,R范围内的最小值. 对于要求2,传统思路是r-l从大到小枚举,每次确定一个(L,R)范围,进行判

CodeForces 1202F(数论,整除分块)

题目 CodeForces 1213G 做法 假设有\(P\)个完整的循环块,假设此时答案为\(K\)(实际答案可能有多种),即每块完整块长度为\(K\),则\(P=\left \lfloor \frac{N}{K} \right \rfloor\) 假设循环快中有\(p_a,p_b\)个\(A\)和\(B\),则 \(p_a\cdot P\le a\Longrightarrow p_a\le \left \lfloor \frac{a}{P} \right \rfloor\) \(p_a\cd