题解 | #Counting Triangles#
Counting Triangles
https://ac.nowcoder.com/acm/contest/11254/J
n个点存在 cn3 即n(n-1)(n-2)/3! 个点
对于一个三边颜色不同的三角形存在两条颜色相同的边和一条颜色不同的边 既存在两个三角形角的两角边为异***r>故不满足条件的三角形个数=异色角个数/2; 满足条件的三角形个数便为 n(n-1)(n-2)/3!-异色角个数/2;
异色角的个数为对于两两点之间颜色为白的边与颜色为黑的边构成的角
O(n²) 求出每两点之间的异色边=黑色边*白色边(总边数n-1 - 黑色边)累加
include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace GenHelper
{
unsigned z1, z2, z3, z4, b, u;
unsigned get()
{
b = ((z1 << 6) ^ z1) >> 13;
z1 = ((z1 & 4294967294U) << 18) ^ b;
b = ((z2 << 2) ^ z2) >> 27;
z2 = ((z2 & 4294967288U) << 2) ^ b;
b = ((z3 << 13) ^ z3) >> 21;
z3 = ((z3 & 4294967280U) << 7) ^ b;
b = ((z4 << 3) ^ z4) >> 12;
z4 = ((z4 & 4294967168U) << 13) ^ b;
return (z1 ^ z2 ^ z3 ^ z4);
}
bool read() {
while (!u) u = get();
bool res = u & 1;
u >>= 1; return res;
}
void srand(int x)
{
z1 = x;
z2 = (x) ^ 0x233333333U;x) + 51;
z3 = x ^ 0x1234598766U;
z4 = (
u = 0;
}
}
using namespace GenHelper;
bool edge[8005][8005];
int main()
{
int n, seed;
ll ans = 0;
cin >> n >> seed;
srand(seed);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
edge[j][i] = edge[i][j] = read();
for (int i = 0; i < n; i++)
{
ll dg = 0;
for (int j = 0; j < n; j++)
if (edge[i][j])++dg;
ans += dg * (n - 1 - dg);
}
printf("%lld", (long long)n * (n - 1) * (n - 2) / 6 - ans / 2);
return 0;
}