给定序列
首先不难想到三元组满足
然后考虑正难则反,直接求不好求,考虑先求
显然要去掉的就是有两个数相同的组合数和有三个数相同的组合数。当然这个从容斥的角度来看三个数相同的似乎应该是加上,但是实现的时候会发现这个实际上不算是容斥。
我们实现的时候不难发现值域较小,于是想到需要建桶。枚举每个桶,令
xxxxxxxxxx56123
45678910
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 初稿