CF1007B]Pave the Parallelepiped[组合计数+状态压缩]

  • 我们把三个数的所有因子用 2^3−1 个状态表示这个数是 A,B,C中的哪几个数字的因子。

  • 按照从小到大的顺序枚举3个数对应的集合,首先保证能够找到一种对应方式(每个数对应是谁的因子),相同的数集利用插板法计算方案避免重复。

  • #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <map>
    #include <vector>
    
    using namespace std;
    
    int t;
    
    int cnt[15];
    int mp[100005];
    int vis[100005];
    int l;
    void divi(int x,int id)
    {
        for(int i=1;i*i<=x;i++)
        {
            if(x%i==0)
            {
                if(vis[i]!=l)
                    mp[i]=0,vis[i]=l;
    
                int pre=mp[i];
                int cur=(pre | (1<<id));
                cnt[pre]--;
                cnt[cur]++;
                mp[i]=cur;
    
                int ti=x/i;
                if(ti!=i)
                {
                    if(vis[ti]!=l)
                        mp[ti]=0,vis[ti]=l;
    
                    pre=mp[ti];
                    cur=(pre | (1<<id));
                    cnt[pre]--;
                    cnt[cur]++;
                    mp[ti]=cur;
                }
            }
        }
    }
    
    long long C(long long b,long long a)
    {
        if(a==1)
            return b;
        if(a==2)
            return b*(b-1)/2;
        if(a==3)
            return b*(b-1)*(b-2)/6;
    }
    
    bool check(int a,int b,int c)
    {
        int t1=a&1,t2=b&2,t3=c&4;
        if(t1 && t2 && t3)
            return true;
    
        t1=a&1,t2=b&4,t3=c&2;
        if(t1 && t2 && t3)
            return true;
    
        t1=a&2,t2=b&1,t3=c&4;
        if(t1 && t2 && t3)
            return true;
    
        t1=a&2,t2=b&4,t3=c&1;
        if(t1 && t2 && t3)
            return true;
    
        t1=a&4,t2=b&2,t3=c&1;
        if(t1 && t2 && t3)
            return true;
    
        t1=a&4,t2=b&1,t3=c&2;
        if(t1 && t2 && t3)
            return true;
    
        return false;
    }
    int main() {
    
        while(~scanf("%d",&t))
        {
            for(l=0;l<t;l++)
            {
                memset(cnt,0,sizeof(cnt));
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                divi(a,0);divi(b,1);divi(c,2);
    
                long long ans=0;
    
                for(int i=1;i<8;i++)
                {
                    for(int j=i;j<8;j++)
                    {
                        for(int k=j;k<8;k++)
                        {
                            if(check(i,j,k))
                            {
                                long long tans;
                                if(i!=j && j!=k && i!=k)
                                {
                                    tans=1ll*cnt[i]*cnt[j]*cnt[k];
                                }
                                else if(i==j && j==k)
                                {
                                    long long num=cnt[i];
                                    tans=C(num,3)+C(num,2)*2+C(num,1);
                                }
                                else
                                {
                                    long long num1,num2;
                                    if(i==j)
                                        num2=cnt[i],num1=cnt[k];
                                    if(j==k)
                                        num2=cnt[j],num1=cnt[i];
                                    if(i==k)
                                        num2=cnt[i],num1=cnt[j];
    
                                    tans=num1*(C(num2,2)+C(num2,1));
                                }
                                ans+=tans;
                            }
                        }
                    }
                }
                printf("%lld\n",ans);
            }
        }
        return 0;
    }

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值