D. Pave the Parallelepiped[组合数学+位运算判断集合包含关系]

D. Pave the Parallelepiped

题意:给定三个数A,B,C(1e5),这三个数分别选一个因数,a,b,c. 满足情况a<=b<=c,问有多少个满足的组合

思路:将集合ABC这3个集合,划分成7个集合,暴力枚举三个数从7个中哪3个选.并利用几何编号的关系判断集合的包含关系.


#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int MOD=1e9+7;
ll cnt[N];
bool isok(int i,int j,int k){
    return ((i&1)+(j&2)+(k&4))==7?true:false;
}

bool check(int i,int j,int k){
    if(isok(i,j,k)||isok(i,k,j)||isok(j,i,k)||isok(j,k,i)||isok(k,i,j)||isok(k,j,i))    return true;
    return false;
}

ll cul2(ll x){//这个证明写几个数字就知道了
    return (x+1)*x/2;
}

ll cul3(ll x){//这个证明写几个数字就知道了,用到平方和公式
    return (x+1)*(x+2)*x/6;
}

void solve(){
    ll st[50];
    ll a,b,c;
    cin >>a >>b >> c;
    ll ab=cnt[__gcd(a,b)],ac=cnt[__gcd(a,c)],bc=cnt[__gcd(b,c)];
    ll abc=cnt[__gcd(__gcd(a,b),c)];
    st[1]=cnt[a]-ab-ac+abc;
    st[2]=cnt[b]-ab-bc+abc;
    st[4]=cnt[c]-ac-bc+abc;
    st[3]=ab-abc;
    st[5]=ac-abc;
    st[6]=bc-abc;
    st[7]=abc;
    ll ans=0;
    for(int i=1;i<=7;i++){//枚举
        for(int j=i;j<=7;j++){
            for(int k=j;k<=7;k++){
                if(check(i,j,k)){
                    if(i==j&&i==k)  ans+=cul3(st[i]);
                    else if(i==j)   ans+=cul2(st[i])*st[k];
                    else if(i==k)   ans+=cul2(st[i])*st[j];
                    else if(j==k)   ans+=cul2(st[j])*st[i];
                    else    ans+=st[i]*st[j]*st[k];
                }
            }
        }
    }
    cout << ans << endl;

}

int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    for(int i=1;i<=100000;i++)//预处理每一个数的因数个数
        for(int j=i;j<=100000;j+=i) cnt[j]++;
    int t;
    cin >>t ;
    while(t--){
        solve();
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Haipai1998/article/details/81045512