给定序列
首先不难想到三元组满足
然后考虑正难则反,直接求不好求,考虑先求
显然要去掉的就是有两个数相同的组合数和有三个数相同的组合数。当然这个从容斥的角度来看三个数相同的似乎应该是加上,但是实现的时候会发现这个实际上不算是容斥。
我们实现的时候不难发现值域较小,于是想到需要建桶。枚举每个桶,令
xxxxxxxxxx
561
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N;
26int a[210000];
27int cnt[210000];
28ll ans(0);
29
30int main(){
31 N = read();
32 for(int i = 1; i <= N; ++i)cnt[a[i] = read()]++;
33 ans = (ll)N * (N - 1) * (N - 2) / (3 * 2 * 1);
34 for(int i = 1; i <= 201000; ++i){
35 if(cnt[i] >= 2)ans -= (ll)cnt[i] * (cnt[i] - 1) / (2 * 1) * (N - cnt[i]);
36 if(cnt[i] >= 3)ans -= (ll)cnt[i] * (cnt[i] - 1) * (cnt[i] - 2) / (3 * 2 * 1);
37 }printf("%lld\n", ans);
38 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
39 return 0;
40}
41
42template < typename T >
43inline T read(void){
44 T ret(0);
45 int flag(1);
46 char c = getchar();
47 while(c != '-' && !isdigit(c))c = getchar();
48 if(c == '-')flag = -1, c = getchar();
49 while(isdigit(c)){
50 ret *= 10;
51 ret += int(c - '0');
52 c = getchar();
53 }
54 ret *= flag;
55 return ret;
56}
update-2022_12_03 初稿