题意:

有n个球,每个球有两个值,一个是颜色,另一个是重量。可以进行如下的操作任意次:

1.选择两个颜色相同的球,如果这两个球的重量之和小于等于X,就交换这两个球;

2.选择两个颜色不同的球,如果这两个球的重量之和小于等于Y,就交换这两个球。

问最后能够得到的本质不同的颜色的序列有多少个。

数据范围:

1<=n,color<=10^5

其余值均<=10^5

思路:

假如说X=INF,Y=INF,那么这道题就是一道重排的题目了。

现在有了X和Y的限制,那么就可以考虑到底哪些球是“自由”的,也就是可以互相随意变更位置。因为如果a能够和b交换位置,b能够和c交换位置,那么a就能够和c交换位置,也就是说交换是具有传递性的,那么我们就只需要考虑所有的球能否和在X和Y的交换含义下的重量最小的球进行交换,就可以了。然后我们把两个点可以交换看成一条边,最后与重量最小的球相连的点就是所有的可以自由移动的点了。

首先考虑X。

那么这个时候就是看同种颜色的交换能否进行。加入说当前的球为i,颜色为c[i],重量为w[i],那么再假设颜色为c[i]的最小重量的球为minpos[c[i]]。如果说\(w[minpos[c[i]]]+w[i]<=X\),那么就说明当前的第i个球是能够进行同种颜色的转移的。

然后考虑Y。

这个时候就是看颜色不同的球能否互相转移。假设全局重量最小的球颜色mnp1,与mnp1颜色不同的最小球为mnp2,对于一个球来说,只需要考虑w[i]+w[mnp1]<=Y或者是w[i]+w[mnp2]<=Y就可以了。因为假设两个球能够和其中的一个同时连边,显然就可以达成目标了;假设两个球只能够和两个球分别连边(颜色所迫),有因为这两个球的重量是分别是>=w[mnp1],>=w[mnp2]的,所以说w[mnp1]和w[mnp2]也一定能够连起来,就可以让这两个球联通了。

最后从全局最小的球mnp1出发,跑一遍DFS,将所有的与mnp1联通的球都打上vis标记,表示这些球都是能够随意换位置的自由球。然后对于剩余的没有打上vis标记的点来说,要么是根本就没有连边,要么就是与自己颜色的最小球连了边,然而后者是没有用的,因为是求颜色序列的方案数。然后相当于就是那些球的位置就已经固定死了,假如自由球的序列已经确定了,那么这些球的位置也相对固定了。

然后对于自由球来说,就是一个重排的问题了。可以用重排的公式求出,也可以直接用\(\sum C_{tot}^{cnt_{color_i}}\)求出。那么问题得到解决。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define MAXN 200000
#define MO 1000000007
#define INF 0x3FFFFFFF
using namespace std;
int n,X,Y;
int c[MAXN+5],w[MAXN+5];
int fact[MAXN+5],inv[MAXN+5];
int minpos[MAXN+5],minval[MAXN+5];//代表的是某种颜色的最小重量以及球的编号
int cnt[MAXN+5];
bool vis[MAXN+5];
vector<int> G[MAXN+5];
int PowMod(int a,int b)
{
int ret=1;
while(b)
{
if(b&1)
ret=1LL*ret*a%MO;
a=1LL*a*a%MO;
b>>=1;
}
return ret;
}
void Init()
{
for(int i=0;i<=MAXN+3;i++)
minval[i]=INF;
fact[0]=1;
for(int i=1;i<=MAXN;i++)
fact[i]=1LL*fact[i-1]*i%MO;
inv[MAXN]=PowMod(fact[MAXN],MO-2);
for(int i=MAXN-1;i>=0;i--)
inv[i]=1LL*inv[i+1]*(1LL*i+1LL)%MO;
}
void DFS(int u)//使用DFS求出所有的与mnp1联通的球
{
vis[u]=true;
for(int i=0;i<(int)G[u].size();i++)
{
int v=G[u][i];
if(vis[v]==false)
DFS(v);
}
}
int C(int a,int b)
{
return 1LL*fact[a]*inv[b]%MO*inv[a-b]%MO;
}
int main()
{
Init();
scanf("%d %d %d",&n,&X,&Y);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&c[i],&w[i]);
if(minval[c[i]]>w[i])
{
minval[c[i]]=w[i];
minpos[c[i]]=i;
}
}
for(int i=1;i<=n;i++)
if(i!=minpos[c[i]]&&w[i]+minval[c[i]]<=X)
G[i].push_back(minpos[c[i]]),G[minpos[c[i]]].push_back(i);//同种颜色的建图
int mn1=INF,mn2=INF;
int mnp1,mnp2;
//先找最小值
for(int i=1;i<=n;i++)
if(w[i]<mn1)
mn1=w[i],mnp1=i;
//再找与最小值颜色不同的最小值
for(int i=1;i<=n;i++)
if(w[i]<mn2&&c[i]!=c[mnp1])
mn2=w[i],mnp2=i;
for(int i=1;i<=n;i++)
{
if(i==mnp1)//全局最小球当然不需要和自己连边
continue;
if(c[i]!=c[mnp1]&&w[i]+w[mnp1]<=Y)//与最小球颜色不同
G[i].push_back(mnp1),G[mnp1].push_back(i);
if(mn2!=INF&&c[i]!=c[mnp2]&&w[i]+w[mnp2]<=Y)//与最小球颜色相同 eles if也可以
G[i].push_back(mnp2),G[mnp2].push_back(i);
}
DFS(mnp1);
for(int i=1;i<=n;i++)
if(vis[i]==true)
cnt[c[i]]++;
int tot=0,ans=1;
for(int i=1;i<=n;i++)
tot+=cnt[i];
for(int i=1;i<=n;i++)
if(cnt[i])
{
ans=1LL*ans*C(tot,cnt[i])%MO;//用法二求出答案
tot-=cnt[i];
}
printf("%d\n",ans);
return 0;
}

【AtCoder】【组合数学】【模型转换】Colorful Balls(AGC012)的更多相关文章

  1. 前端MVVM框架avalon - 模型转换1

    轻量级前端MVVM框架avalon - 模型转换(一) 接上一章 ViewModel modelFactory工厂是如何加工用户定义的VM? 附源码 洋洋洒洒100多行内部是魔幻般的实现 1: fun ...

  2. 将List 中的ConvertAll的使用:List 中的元素转换,List模型转换, list模型转数组

    一,直接入代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using S ...

  3. Verification of Model Transformations A Survey of the State-of-the-Art 模型转换的验证 对现状的调查

    模型驱动工程范式认为软件开发生命周期由工件(需求规范.分析和设计文档.测试套件.源代码)支持,这些工件是表示要构建的系统不同视图的模型.存在一个由模型转换驱动的(半)自动构造过程,从系统的抽象模型开始 ...

  4. AT2364 Colorful Balls

    AT2364 Colorful Balls 题意翻译 N个球排成一排,第i个球有颜色ci和重量wi. Snuke每次可以选择两个颜色相同,且重量之和不超过X的球,交换他们的位置. Snuke每次可以选 ...

  5. 【tensorflow-v2.0】如何将模型转换成tflite模型

    前言 TensorFlow Lite 提供了转换 TensorFlow 模型,并在移动端(mobile).嵌入式(embeded)和物联网(IoT)设备上运行 TensorFlow 模型所需的所有工具 ...

  6. noip2019集训测试赛(二十一)Problem A: Colorful Balls

    Problem A: Colorful Balls Description Snuke放了N个一排彩色的球.从左起第i个球的颜色是ci重量是wi她可以通过执行两种操作对这些球重新排序操作1:选择两个相 ...

  7. 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)

    洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...

  8. 【机器学习】使用CNN神经网络实现对图片分类识别及模型转换

    仅做记录,后面慢慢整理 训练函数: from skimage import io, transform # skimage模块下的io transform(图像的形变与缩放)模块 import glo ...

  9. Bitter.Core系列六:Bitter ORM NETCORE ORM 全网最粗暴简单易用高性能的 NETCore ORM 之 示例 DataTable 模型转换

    当我们查询之前,我们先构造一个查询对象的输出DTO.如下图代码: public class TScoreSearchDto { /// <summary> /// 分数 /// </ ...

  10. CF1478-A. Nezzar and Colorful Balls

    CF1478-A. Nezzar and Colorful Balls 题意: 有\(n\)个球,每个球上面都有一个数字\(a_i\),这些数字是组成的序列是非递减的.现在你要给每个球涂色,你必须保证 ...

随机推荐

  1. hdu 1848 简单SG函数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1848 Problem Description 任何一个大学生对菲波那契数列(Fibonacci num ...

  2. SignarL服务器端发送消息给客户端的几种情况

    一.所有连接的客户端 Clients.All.addContosoChatMessageToPage(name, message); 二.只发送给呼叫的客户端(即触发者) Clients.Caller ...

  3. (四)窗口mainwindow

    常用控件: lable: 可以放文本,图片,动态图片,链接 Text Edit: 富文本编辑框:多行文本,HTML,图片 Line Edit:  只能放一行 Plain Edit: 只能显示多行文本 ...

  4. iOS开发者知识普及,Swift 挑战 Objective-C,谁会笑到最后?

    前言: 目前全球共有超过 7 亿台 iPhone 处于活跃状态,全球约有2000万名 iOS 开发者,这造就了 iOS 作为全球第二大移动设备平台的状态. 虽然安卓系统的全球市场占有率超过 iOS 系 ...

  5. utf8mb4的大小写敏感性测试及其修改方法

    utf8mb4的大小写敏感性测试及其修改方法 utf8mb4_ unicode_ ci 与 utf8mb4_ general_ ci 如何选择字符除了需要存储,还需要排序或比较大小,涉及到与编码字符集 ...

  6. sql注入学习 sqlliab教程 lesson1 (sqlliab搭建教程)

    靶场搭建 小白建议直接用集成环境.推荐laragon (由于这套靶场较早,需要使用php7.0以下环境,安装完php laragon需要在安装php低版本,默认laragon只集成了一个7.0的php ...

  7. MySQL学习7 - 外键的变种 三种关系

    一 介绍 二 如何找两张表之间的关系 三 表的三种关系 1.书和出版社 2.作者和书籍的关系 3.用户和博客 本节的重点 如何找出两张表之间的关系 表的三种关系 一 介绍 因为有foreign key ...

  8. linux磁盘空间满?

    磁盘空间满啦 找到项目的logs文件夹 进入logs文件夹,会看到很多access.log*文件. 在Xshell里,输入命令cd 到项目节点的logs文件夹 可能还需要清空下回收站.

  9. Django之会议室预预订

    model表设计: from django.db import models from django.contrib.auth.models import AbstractUser # Create ...

  10. js设置document.domain实现跨域

    document.domain 只能实现跨子域的问题 如:xxx.com/a.html 和aaa.xxx.com/b.html 或:bbb,xxx.com/c.html 和ccc.xxx.com/d. ...