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;
}

  

彼时当年少,莫负好时光。
原文地址:https://www.cnblogs.com/l609929321/p/9334536.html