• HDU_4390 Number Sequence (容斥原理)


      题目:a1*a2*...*an=b1*b2*…*bn,(ai > 1) 给出b序列,求a序列有多少种。

    先不考虑ai > 1这个条件。可以通过费解b_i的质因子得到如下公式:

    ∏b_i = ∏(p_i^k_i);

    pi是∏bi 的某个质因子。

    因为a_i 共有n个,所以把每个p_i填到这n个空位置里边去。对于p_i,有C(k_i + n - 1, n - 1);

    证明见:http://hi.baidu.com/pp_5/blog/item/73798043ec77781f72f05d51.html/cmtid/6aff22f08c5c85a1a50f523d 

    显然,所有的p[]的值为 ∏C(k_i + n - 1, n - 1); (上午问ftiasch❤trl大牛时就是这个地方没想明白。。。让他体会了一把对牛弹琴的感觉。。。深表歉意。)

    然后考虑ai > 1这个条件。

     已知容次原理:

      

    设Ai表示i位置为1这种状态。 则 answer = 

    根据容斥原理枚举Ai, Aj, Ak...位置为1的状态。。。。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <map>
    #include <sstream>
    
    #define CL(arr, val)    memset(arr, val, sizeof(arr))
    #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   x < y ? x : y
    #define Max(x, y)   x < y ? y : x
    #define E(x)    (1 << (x))
    
    const double eps = 1e-4;
    typedef long long LL;
    const int inf = ~0u>>2;
    using namespace std;
    
    const int N = 110;
    const int M = 1000010;
    const int MOD = 1e9 + 7;
    
    int c[N][N];
    int k[M], t[M];
    int num, n;
    
    int prime[N*20];
    bool vis[N*20];
    int cnt;
    
    void get_prime() {
        CL(vis, true);
        int i, j;
        for(i = 2; i < N*20; ++i) {
            for(j = i*i; j < N*20; j += i) {
                vis[j] = false;
            }
        }
        cnt = 0;
        for(i = 2; i < N*20; ++i) {
            if(vis[i])  prime[cnt++] = i;
        }
    }
    
    void init() {
        get_prime();
        CL(c, 0);
        int i , j;
        for(i = 0; i < N; ++i)  c[i][0] = c[i][i] = 1;
        for(i = 2; i < N; ++i) {
            for(j = 1; j < i; ++j) {
                c[i][j] = (c[i-1][j] + c[i-1][j-1])%MOD;
            }
        }
    }
    
    LL solve(int x) {
        int m = n, flag = 1, i;
    
        for(i = 0; i < n; ++i) {
            if(((1<<i)&x) == 0) {
                flag *= -1; m--;
            }
        }
        LL tmp = 1;
        for(i = 0; i < num; ++i) {
            tmp = tmp*LL(c[k[i]+m-1][m-1])%MOD;
        }
        //printf("%d\n", tmp*flag);
        return tmp*flag;
    }
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        init();
        int x, i, j;
        LL ans;
    
        while(~scanf("%d", &n)) {
            CL(t, 0);
            for(i = 0; i < n; ++i) {
                scanf("%d", &x);
                for(j = 0; prime[j]*prime[j] <= x; ++j) {
                    if(x%prime[j] == 0) {
                        while(x%prime[j] == 0) {
                            t[prime[j]]++; x /= prime[j];
                        }
                    }
                }
                if(x != 1)   t[x]++;
            }
            num = 0;
            for(i = 2; i < M; ++i) {
                if(t[i] != 0) {
                    k[num++] = t[i];
                }
            }
            ans = 0;
           //从N状态开始枚举。。。二进制位为1表示那一位的a_i不等于1,为0则表示等于1。因为proh(a_i) = proh(b_i)所以,a_i不可能全为0。。。
            for(i = (1<<n)-1; i >= 1; --i) {
                ans = (ans + solve(i))%MOD;
            }
            cout << (ans%MOD + MOD)%MOD << endl;
        }
        return 0;
    }
  • 相关阅读:
    Kakuro Extension HDU
    CodeForces
    HDU
    2019牛客暑期多校训练营(第二场)F.Partition problem
    UVA
    团队冲刺6
    团队冲刺4
    团队冲刺3
    团队冲刺2
    团队冲刺1
  • 原文地址:https://www.cnblogs.com/vongang/p/2654435.html
Copyright © 2020-2023  润新知