-
我们把三个数的所有因子用 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; }