组合数学 + 并查集 - Little W and Contest - HDU 6795

在这里插入图片描述
题意:

就是有两类人,第一类人的能量值为1,第二类人的能量值为2,你要从中选择三个人且加起来的能量值不能小于5而且这三个人必须是互不相识的。
还需满足的要求:
1.开始时他们互不相识,认识是有传递性的 比如A认识B B认识C 那么A也认识C
2.每次输入两个整数,输入之后代表这两个人认识了,输入n-1次,使得最后每个人都互相认识。

样例输入:

1
5
2 2 2 1 1
4 5
1 4
2 1
3 2

样例输出:

7
7
3
0
0

分析:

把有关系的放在一个集合通过并查集,并且用两个数组分别记录每一个集合中能量值为2和能量值为1的人数。

代码

在这里插入代码片
#include <bits/stdc++.h>

#define ll long long
using namespace std;

int a[100001];
int vis[100001];
int p2[100001]; //该节点的集合下为2的个数
int p1[100001];//该节点的集合下为1的个数
int fa[100001]; //相互之间具有关系的人放在一起
int cnt1=0,cnt2=0;
ll mod=1e9+7;
int fac(int x){

    return fa[x]==x?x:fa[x]=fac(fa[x]);
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);
    int t;
    cin>>t;
    while(t--){
       int n;
       cin>>n;
       cnt1=0,cnt2=0;
       for (int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]==1){
            p1[i]=1;
            p2[i]=0;
            fa[i]=i;
            cnt1++;
        }
        else{
          p1[i]=0;
            p2[i]=1;
            fa[i]=i;
            cnt2++;
        }
       }
       ll ans=(cnt1*cnt2*(cnt2-1)/2%mod+cnt2*(cnt2-1)*(cnt2-2)/6%mod)%mod;
       // C cnt2中取3  cnt2中取2cnt1 中取1
       cout<<ans<<endl;
       for (int i=0;i<n-1;i++){
        //每次在上一次的ans上减去先增加的关系中不满足的情况
        //增加新关系之后 相对于上一次减去增加的新关系中不符合要求的
        //考虑再新增加一个关系x y之后,相对于上一次的关系,
      //  分为三部分,一部分为fa[x],fa[y],还有一部分就是剩余的
    //    相对于上一次的所有情况中,增加这个关系之后,不满足的选择有四种,
       // 从fa[x] 集合中选择一个 fx[y]集合中选择一个 剩余的集合中选择一个
       // 分别选择的能力值为2 2 1 
       //      2 1 2  1 2 2  2 2 2
        //如果你认为从只从fa[x]或fa[y]集合中选择三个满足能力值大于5的三个人也为
       // 不满足的情况,那这个认为是错误的,因为fa[x]这个集合里面的元素都是有关系的,
        //而在上一次求得的ans中没有加入这种情况,只是加入新增加的四种情况。
          int x,y;
          cin>>x>>y;
          int fx=fac(x);
          int fy=fac(y);
          ll k=0; //k 为不符合条件的那些人
     
           k= (ll)p2[fx]*p2[fy]*(cnt1-p1[fx]-p1[fy])%mod;// 2 2 1
           k=(k+(ll)p2[fx]*p1[fy]*(cnt2-p2[fx]-p2[fy]))%mod; // 2 1 2
           k=(k+(ll)p1[fx]*p2[fy]*(cnt2-p2[fx]-p2[fy]))%mod; // 1 2 2
           k=(k+(ll)p2[fx]*p2[fy]*(cnt2-p2[fx]-p2[fy]))%mod; // 2 2 2
           ans=(ans-k+mod)%mod;
           cout<<ans<<endl;
       fa[fy]=fx;
       p1[fx]+=p1[fy];
       p2[fx]+=p2[fy];
       p1[fy]=0,p2[fy]=0;
       }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的数据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域数据量爆炸的今天,各行业都希望通过数据处理与分析手段,得到数据中有价值的信息,以便明确客户的需求和指引企业的发展。
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的数据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域数据量爆炸的今天,各行业都希望通过数据处理与分析手段,得到数据中有价值的信息,以便明确客户的需求和指引企业的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值