zoukankan      html  css  js  c++  java
  • CF1007B Pave the Parallelepiped 容斥原理

    Pave the Parallelepiped
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    You are given a rectangular parallelepiped with sides of positive integer lengths AA, BB and CC.

    Find the number of different groups of three integers (aa, bb, cc) such that 1abc1≤a≤b≤c and parallelepiped A×B×CA×B×C can be paved with parallelepipeds a×b×ca×b×c. Note, that all small parallelepipeds have to be rotated in the same direction.

    For example, parallelepiped 1×5×61×5×6 can be divided into parallelepipeds 1×3×51×3×5, but can not be divided into parallelepipeds 1×2×31×2×3.

    Input

    The first line contains a single integer tt (1t1051≤t≤105) — the number of test cases.

    Each of the next tt lines contains three integers AA, BB and CC (1A,B,C1051≤A,B,C≤105) — the sizes of the parallelepiped.

    Output

    For each test case, print the number of different groups of three points that satisfy all given conditions.

    Example
    input
    Copy
    4
    1 1 1
    1 6 1
    2 2 2
    100 100 100
    output
    Copy
    1
    4
    4
    165
    Note

    In the first test case, rectangular parallelepiped (1,1,1)(1,1,1) can be only divided into rectangular parallelepiped with sizes (1,1,1)(1,1,1).

    In the second test case, rectangular parallelepiped (1,6,1)(1,6,1) can be divided into rectangular parallelepipeds with sizes (1,1,1)(1,1,1), (1,1,2)(1,1,2), (1,1,3)(1,1,3) and (1,1,6)(1,1,6).

    In the third test case, rectangular parallelepiped (2,2,2)(2,2,2) can be divided into rectangular parallelepipeds with sizes (1,1,1)(1,1,1), (1,1,2)(1,1,2), (1,2,2)(1,2,2) and (2,2,2)(2,2,2).

    这题目其实求的就是a的因子乘b的因子乘c的因子

    所以重点是算出a,b,c的因子

    但是中间会出现重复的情况,比如(1,1,2),(1,2,1)是同一种情况

    所以我们还要用容斥原理去掉这种情况

    情况分为四种:a,b重负的情况;a,c重复的情况;b,c重复的情况;a,b,c重复的情况

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define A 0
    #define B 1
    #define C 2
    #define AB 3
    #define BC 4
    #define AC 5
    #define ABC 6
    #define debug(a) cout << #a << " " << a << endl
    using namespace std;
    const int maxn = 1e5;
    const int mod = 10000007;
    typedef long long ll;
    ll t, a, b, c, kt[5],p[10], nu[maxn+10], num[maxn+10];
    ll gcd( ll a, ll b) {
        return b==0?a:gcd(b,a%b);
    }
    map<ll,ll>mm;
    vector<ll> va, vb, vc;
    void init() { //预处理每个数因子的数量
        for( ll i = 1; i <= maxn; i ++ ) {
            for( ll j = i; j <= maxn; j +=i ) {
                nu[j] ++;
            }
        }
        va.push_back(A);  va.push_back(AB);
        va.push_back(AC); va.push_back(ABC);
    
        vb.push_back(B);  vb.push_back(AB);
        vb.push_back(BC); vb.push_back(ABC);
    
        vc.push_back(C);  vc.push_back(AC);
        vc.push_back(BC); vc.push_back(ABC);
    }
    
    ll cal3( ll x) {
        ll res = 0;
        res += x + x*(x-1) + x*(x-1)*(x-2)/6;//三部分取相同,两部分取相同,三部分都不同
        return res;
    }
    
    ll cal2( ll x ) {
        ll res = 0;
        res += x + x*(x-1)/2;//两部分相同,两部分不同
        return res;
    }
    int main() {
        init();
        cin >> t;
        while(t--)
        {
            cin >> a >> b >> c;
            ll ab = gcd(a,b), bc = gcd(b,c), ac = gcd(a,c);
            ll abc = gcd(ab,c);
            ll nABC = nu[abc];
            ll nAB = nu[ab] - nABC, nBC = nu[bc] - nABC, nAC = nu[ac] - nABC;
            ll nA = nu[a] - nAB - nAC - nABC, nB = nu[b] - nAB - nBC - nABC;
            ll nC = nu[c] - nAC - nBC - nABC;
            num[ABC] = nABC;
            num[AB] = nAB, num[AC] = nAC, num[BC] = nBC;
            num[A] = nA, num[B] = nB, num[C] = nC;
            ll ans = 0;
            mm.clear();
            for( ll i = 0; i < va.size(); i ++ ) {
                for( ll j = 0; j < vb.size(); j ++ ) {
                    for( ll k = 0; k < vc.size(); k ++ ) {
                        kt[0] = va[i], kt[1] = vb[j], kt[2] = vc[k];
                        sort( kt, kt+3 );
                        ll x = kt[0], y = kt[1], z = kt[2];
                        ll tmp = 0;
                        for( ll l = 0; l < 3; l ++ ) {
                            tmp=1ll*tmp*maxn+1ll*kt[l];
                        }
                        if( mm[tmp] ) continue;///打标记去重
                        mm[tmp] = 1;
                        if( x == y && y == z )
                            ans += cal3(num[x]);
                        else if( x == y )
                            ans += num[z]*cal2(num[x]);
                        else if( y == z )
                            ans += num[x]*cal2(num[y]);
                        else ans += num[x]*num[y]*num[z];
                    }
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
    

      

    彼时当年少,莫负好时光。
  • 相关阅读:
    14.[保护模式]TSS任务段
    13.[保护模式]陷阱门
    12.[保护模式]中断门
    11.[保护模式]调用门
    10.[保护模式]长调用与短调用
    9.[保护模式]代码的跨段跳转流程
    8.[保护模式]段权限检查
    7.[保护模式]段描述符DB位
    6.[保护模式]段描述符属性_S位_TYPE域
    5.[保护模式]段描述符属性_P位_G位
  • 原文地址:https://www.cnblogs.com/l609929321/p/9334536.html
Copyright © 2011-2022 走看看