2021-09-04 2021牛客多校训练营3 J 题题解

来写一写之前打的牛客多校训练营3的J题的题解,一开始被这题目上的代码吓到了,还以为是很难的题目,后来发现不是很难,只要想到了思路就能很快实现。


# 题目描述 链接:https://ac.nowcoder.com/acm/contest/11254/J 来源:牛客网

Goodeat finds an undirected complete graph with n vertices. Each edge of the graph is painted black or white. He wants you to help him find the number of triangles (a, b, c) (a < b < c), such that the edges between (a, b), (b, c), (c, a) have the same color. To avoid the input scale being too large, we use the following code to generate edges in the graph.

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;
        z3=x^0x1234598766U;
        z4=(~x)+51;
      	u = 0;
    }
}
using namespace GenHelper;
bool edge[8005][8005];
int main() {
  int n, seed;
  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();
 	return 0;
}

The edge array in the above code stores the color of the edges in the graph. edge[i][j]=1 means that the edge from i to j is black, otherwise it is white (\forall 0 \le i \neq j \le n-1∀0≤i
=j≤n−1).Ensure that there is an approach that does not depend on the way the data is generated.

题目思路

三角形由两种角组成,一种角是由两个相同的边组合的,另一种角是由两个不同的边组合的。
设这种角为a和b;
而三角形只有两种,一种是一个角a和两个角b组成的a1,另一种是由三个角b组成的b1,只有这两种情况。
所以要求三条边都相同的三角形b1的个数我们只需要求出角a的个数x,角b的个数y。
因为角a只有三角形a1有,所以三角形a1的个数就为x,所以三角形b1的个数即为(y-2x)/3.

代码


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;
        z3=x^0x1234598766U;
        z4=(~x)+51;
      	u = 0;
    }
}
using namespace GenHelper;
#include<iostream>
using namespace std;
bool edge[8005][8005];
int main() 
{
  int n, seed;
  long long a=0,b=0,x,y;
  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();
     x=0;y=0;
    for(int i=0;i<n;i++)
    {
        x=0;y=0;
        for(int j=0;j<n;j++)
        {
            if(j!=i)
            {
                if(edge[i][j]==1)x++;
                else y++;
            }
            else continue;
        }
        b=x*(x-1)/2+y*(y-1)/2+b;
        a=x*y+a;
    }
    cout<<(b-a/2)/3;
 	return 0;
}

总结

不要被那些看上去很长很难的题目吓到,有可能它不是很难。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值