HDU 4390 Number Sequence(容斥)

博客围绕数字序列问题展开,给定序列b1,b2…bn,求满足a1a2…an=b1b2*…bn(ai>1)的序列a1,a2,…,an的个数。介绍了输入输出格式及样例,题解是先分出bi素因子,用组合数计算,再通过容斥原理处理空位问题。

Number Sequence

Given a number sequence b 1,b 2…b n.
Please count how many number sequences a 1,a 2,…,a n satisfy the condition that a 1a 2a n=b 1b 2*…b n (a i>1).
Input
The input consists of multiple test cases.
For each test case, the first line contains an integer n(1<=n<=20). The second line contains n integers which indicate b 1, b 2,…,b n(1<b i<=1000000, b 1
b 2*…*b n<=10 25).
Output
For each test case, please print the answer module 1e9 + 7.

Sample Input

2
3 4

Sample Output

4

Hint
For the sample input, P=3*4=12.
Here are the number sequences that satisfy the condition:
2 6
3 4
4 3
6 2

题意
给出b1∗b2∗⋯∗bnb_1*b_2*\cdots*b_nb1b2bn求能使a1∗a2∗⋯∗an=b1∗b2∗⋯∗bna_1*a_2*\cdots*a_n=b_1*b_2*\cdots*b_na1a2an=b1b2bn的长度为n的an的ana数组的个数,其中ai&gt;1a_i&gt;1ai>1

题解
分出每个bib_ibi的素因子(与素因子大小无关),将m个相同的素因子放在nnn个位置,就是Cn+m−1n−1C_{n+m-1}^{n-1}Cn+m1n1。然后将每个不同的素因子都计算一遍。
但是很明显题中要求ai&gt;1a_i&gt;1ai>1,所以位置不能为空,而我们求的是存在空位置的。因此通过容斥,得ans=无空位计算值−空一位计算值+空两位计算值−⋯ans=无空位计算值-空一位计算值+空两位计算值-\cdotsans=+

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <cmath>

using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
const int maxn = 1e6;
const double INF = 0x3f3f3f3f;
const int MOD = 1e9+7;

int comb[110][110];
void C(){
    for(int i = 0; i <= 50; ++i){
        comb[i][0] = comb[i][i] = 1;
        for(int j = 1; j < i; ++j){
            comb[i][j] = comb[i-1][j]+comb[i-1][j-1];
            comb[i][j] %= MOD;
        }
    }
}


int main(){
    int n;
    int b[22];
    C();
    while(cin>>n){
        for(int i = 1; i <= n; ++i) scanf("%d",&b[i]);
        vector<int>v;
        vector<int>vv;
        for(int i = 1; i <= n; ++i){
            int x=b[i];
            for(int j = 2; j*j <= x; ++j){
                while(x%j == 0){
                    v.push_back(j);
                    x /= j;
                }
            }   
            if(x > 1) v.push_back(x);
        }
        sort(v.begin(),v.end());
        vv.push_back(1);
        for(int i = 1; i < v.size(); ++i){
            if(v[i]!=v[i-1]) vv.push_back(1);
            else vv[vv.size()-1]++;
        }
        ll sum = 0;
        for(int i = 0; i < n; ++i){
            ll ans = comb[n][i];
            for(int j = 0;j < vv.size();++j){
                ans = (ans*comb[vv[j]+n-i-1][n-i-1])%MOD;
            }
            if(i&1) sum = ((sum-ans)%MOD+MOD)%MOD;
            else sum = (sum+ans)%MOD;
        }
        cout<<sum<<endl;
    }
    return 0;
}

/*


*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值