题意:

有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. CodeForces 70

    题目 A题 #include<bits/stdc++.h> using namespace std; int n,b,sum; int main(){ scanf("%d&quo ...

  2. CentOS7使用firewalld防火墙配置端口

    安装启用firewalld防火墙 CentOS7默认的防火墙是firewalld 如果没有firewalld防火墙,可以执行yum install firewalld 命令进行安装 firewalld ...

  3. (二叉树 递归) leetcode 106. Construct Binary Tree from Inorder and Postorder Traversal

    Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  4. Vue过滤器

    局部定义: var vm = new Vue({ el:"#app", data:{ proData:'' }, filters: { pro_color(index){ swit ...

  5. Stacking:Catboost、Xgboost、LightGBM、Adaboost、RF etc

    python风控评分卡建模和风控常识(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005214003&am ...

  6. kubernetes云平台管理实战: 滚动升级秒级回滚(六)

    一.nginx保证有两个版本 1.查看当前容器运行nginx版本 [root@k8s-master ~]# kubectl get pod -o wide NAME READY STATUS REST ...

  7. Hadoop记录-JMX参数

    Yarn metrics参数说明 获取Yarn jmx信息:curl -i http://xxx:8088/jmx Hadoop:service=ResourceManager,name=FSOpDu ...

  8. DirectX11 With Windows SDK--14 深度测试

    前言 当使用加法/减法/乘法颜色混合,或者使用透明混合的时候,在经过深度测试时可能会引发一些问题.例如现在我们需要使用加法混合来绘制一系列对象,而这些对象彼此之间不会相互阻挡.若我们仍使用原来的深度测 ...

  9. 前端面试题整理—jQuery篇

    1.为什么使用jquery,他有哪些好处? 1)轻量级.代码简洁 2)强大的选择器,出色的DOM操作封装 3)有可靠的事件处理机制 4)浏览器兼容性好 5)支持链式操作 6)支持丰富的插件 2.jqu ...

  10. HTML(三)HTML属性

    HTML 属性 属性: [class] 规定元素的一个或多个类 注意: 类不能以数字开头 class = "classA classB" // 多个类的写法 [id] 规定元素的唯 ...