解法
靠测试数据过的……19年没有测试数据恐怕要凉……
比较简单,统计每个数字的出现次数times[i]
当其中2个数的乘积为d
时:
d=0
,乘积为0可以是3个0,和2个0加上一个非0数,所以增加C(times[0],3)+C(times[0],2)*(n-times[0])
d=1
,乘积为1只可能是三个1,所以增加C(times[1],3)
d>1
,最后这种情况比较简单,对d
进行因子分解d=a*b
:- 若
a>1,b>1
:(记得别忘记乘times[d]
)- 如果
a!=b
,那么答案增加times[d]*times[a]*times[b]
- 如果
a==b
,那么答案增加times[d]*C(times[a],2)
- 如果
- 对于
a
和b
里有1的情况,答案增加times[1]*C(times[d],2)
- 若
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#define MAXN 400010
#define MAXQ 100010
#define ZERO 10e-6
using namespace std;
typedef long long lld;
int n;
map<int,int> counter;
int main() {
// freopen("/Users/huangyuemei/CLionProjects/untitled/A-small-practice.in","r",stdin);
// freopen("/Users/huangyuemei/CLionProjects/untitled/my.out","w",stdout);
int t;
scanf("%d",&t);
for(auto round=1;round<=t;++round) {
scanf("%d",&n);
counter.clear();
for(int i=0;i<n;++i) {
int a;
scanf("%d",&a);
counter[a]++;
}
lld ans = 0;
for(auto &key:counter) {
if (key.first <= 1) continue;
int up = sqrt(key.first);
for(int a = 2;a<=up;++a) {
if(key.first % a==0) {
int b = key.first/a;
if(a!=b) ans += (lld)key.second*counter[a]*counter[b];
else ans += (lld)key.second*counter[a]*(counter[a]-1)/2;
}
}
ans += (lld)counter[1]*key.second*(key.second-1)/2;
}
int zeros = counter[0], ones = counter[1];
ans += (lld)zeros*(zeros-1)*(zeros-2)/6+(lld)zeros*(zeros-1)/2*(n-zeros);
ans += (lld)ones*(ones-1)*(ones-2)/6;
printf("Case #%d: %lld\n",round,ans);
}
}