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 C.

Find the number of different groups of three integers (have to be rotated in the same direction.

For example, parallelepiped 1×2×3.

Input

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

Each of the next 1≤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).

In the second test case, rectangular parallelepiped (1,1,6).

In the third test case, rectangular parallelepiped (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;
}

  

相关文章: