Problem A: Colorful Balls

Description

Snuke放了N个一排彩色的球.从左起第i个球的颜色是ci重量是wi
她可以通过执行两种操作对这些球重新排序
操作1:选择两个相同颜色的球,假如他们的重量和小于等于X,交换两个球的位置
操作2:选择两个不同颜色的球,假如他们的重量和小于等于Y,交换两个球的位置
求我们总共可以得到多少种 不同的颜色序列?对答案取109+7的模

Input

N X Y
c1 w1
.
.
.
cN wN

Output

输出答案。

Sample Input

sample input 1:
4 7 3
3 2
4 3
2 1
4 4
sample input 2:
1 1 1
1 1
sample input 3:
21 77 68
16 73
16 99
19 66
2 87
2 16
7 17
10 36
10 68
2 38
10 74
13 55
21 21
3 7
12 41
13 88
18 6
2 12
13 87
1 9
2 27
13 15

Sample Output

sample output 1:
2
sample output 2:
1
sample output 3:
129729600

HINT

1≤N≤2×105

1≤X,Y≤109
1≤ci≤N
1≤wi≤109

分析

首先,如果球A可以和球B交换,球B也可以和球C交换,那么肯定可以通过球B将球A与球C交换。

所以只需要将可以交换的任意两个球之间连一条边,找出每个联通块中每种球颜色的个数,因为每个联通块内无论怎么排都行,所以就能用组合数求出当前那个联通块中合法排列的方案数,最后再将所有的联通块的方案数乘起来就能得到答案了。

但这种方法的时间复杂度是O(n2)的。

但我们可以设:

球a是全部球中重量最小的球。

球b是全部球中与球a不同色且重量最小的球。

若找不出球b,则只有一种颜色的球,故只有1种方案

若球a与球b不在同一个联通块内,则不可能出现两种不同颜色的球在同一个联通块内,故只有1种方案

而对于每一个球来说,如果它既不能连到球a,也不能连到球b,那么它不可能再连到其他异色的球。

所以只可能有1个联通块对答案做出贡献。

所以我们只需要求出所有可以连到球a或球b或连到一个与它同色且能连到球a或球b的球即可。

时间复杂度为O(n)

O(n)的时间求组合数详见欧拉定理

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct data{
long long x,y;
}t[];
long long n,s1,s2,k1,k2,f[],k[],m=,s[],cnt,id[],sum,ans=,col[],colmax[];
bool d[],r[];
bool cmp(data a,data b){
return a.y<b.y;
}
long long get_pow(long long a,long long b){
long long p=;
while(b){
if(b%)p=(p*a)%m;
a=(a*a)%m;
b=b/;
}
return p;
}
long long c(long long a,long long b){
return (((k[a]*f[b])%m)*f[a-b])%m;
}
void add(long long a){
long long p=a;
while(t[col[p]].y+t[a].y<=s1){
if(!col[p])break;
s[t[a].x]++;
sum++;
p=col[p];
r[p]=;
}
}
int main(){
scanf("%lld%lld%lld",&n,&s1,&s2);
k[]=;
for(long long i=;i<=n;i++)k[i]=(k[i-]*i)%m;
f[n]=get_pow(k[n],m-);
for(long long i=n-;i>;i--)f[i]=(f[i+]*(i+))%m;
f[]=;
f[]=;
for(long long i=;i<=n;i++)scanf("%lld%lld",&t[i].x,&t[i].y);
sort(t+,t+n+,cmp);
for(long long i=;i<=n;i++){
col[colmax[t[i].x]]=i;
colmax[t[i].x]=i;
}
k1=;
k2=;
while(k2<=n&&t[k2].x==t[k1].x)k2++;
if(k2!=n+){
if(t[k1].y+t[k2].y<=s2){
for(long long i=;i<=n;i++){
if((t[i].x!=t[k1].x&&t[k1].y+t[i].y<=s2)||(t[i].x!=t[k2].x&&t[k2].y+t[i].y<=s2)){
if(!d[t[i].x]){
d[t[i].x]=;
r[i]=;
cnt++;
id[cnt]=t[i].x;
s[t[i].x]++;
sum++;
add(i);
}else if(!r[i]){
s[t[i].x]++;
r[i]=;
sum++;
}
}
}
for(long long i=;i<=cnt;i++){
ans=(ans*c(sum,s[id[i]]))%m;
sum=sum-s[id[i]];
}
}
}
printf("%lld\n",ans);
}

  

noip2019集训测试赛(二十一)Problem A: Colorful Balls的更多相关文章

  1. noip2019集训测试赛(二十一)Problem B: 红蓝树

    noip2019集训测试赛(二十一)Problem B: 红蓝树 Description 有一棵N个点,顶点标号为1到N的树.N−1条边中的第i条边连接顶点ai和bi.每条边在初始时被染成蓝色.高桥君 ...

  2. noip2017集训测试赛(十一)Problem C: 循环移位

    题面 Description 给定一个字符串 ss .现在问你有多少个本质不同的 ss 的子串 t=t1t2⋯tm(m>0)t=t1t2⋯tm(m>0) 使得将 tt 循环左移一位后变成的 ...

  3. 2016北京集训测试赛(十一)Problem C: 树链问题

    Solution 智障暴力题, 每个点维护一下子树信息, 树剖就好了. 我居然还傻了写了一发毛毛虫... #include <cstdio> #include <cctype> ...

  4. 题解和总结——noip2019集训测试赛(一)贪吃蛇+字符串+都城

    Problem A: 贪吃蛇 描述 Input Output Sample Input [样例输入1] 4 5 ##... ..1#@ 432#. ...#. [样例输出1] 4 [样例输入2] 4 ...

  5. 2016集训测试赛(二十一)Problem C: 虫子

    题目大意 给你一棵树, 每个点有一个点权. 有两种操作: link / cut 修改某个点的点权 每次操作后, 你要输出以下答案: 在整棵树中任意选两个点, 这两个点的LCA的期望权值. Soluti ...

  6. 2016集训测试赛(二十六)Problem A: bar

    Solution 首先审清题意, 这里要求的是子串而不是子序列... 我们考虑用1表示p, -1表示j. 用sum[i]表示字符串前\(i\)的前缀和. 则我们考虑一个字符串\([L, R]\)有什么 ...

  7. 2016集训测试赛(二十四)Problem B: Prz

    Solution 这道题有两个关键点: 如何找到以原串某一个位置为结尾的某个子序列的最晚出现位置 如何找到原串中某个位置之前的所有数字的最晚出现位置中的最大值 第一个关键点: 我们注意到每个数字在\( ...

  8. 2016集训测试赛(二十四)Problem C: 棋盘控制

    Solution 场上的想法(显然是错的)是这样的: 我们假设棋子是一个一个地放置的, 考虑在放置棋子的过程中可能出现哪些状态. 我们令有序整数对\((i, j)\)表示总共控制了\(i\)行\(j\ ...

  9. 2016集训测试赛(二十)Problem B: 字典树

    题目大意 你们自己感受一下原题的画风... 我怀疑出题人当年就是语文爆零的 下面复述一下出题人的意思: 操作1: 给你一个点集, 要你在trie上找到所有这样的点, 满足点集中存在某个点所表示的字符串 ...

随机推荐

  1. 使用WinDbg调试入门(内核模式)

    windbg是一个内核模式和用户模式调试器,包含在Windows调试工具中.这里我们提供了一些实践练习,可以帮助您开始使用windbg作为内核模式调试器. 设置内核模式调试 内核模式调试环境通常有两台 ...

  2. PowerDesigner 画流程图

    原因: 以前赶时间写了n长一个类,现在又增加新需求了,but以前怎么写的忘了,虽然注释都有,一个一个方法的看很累,准备把它用面向对象改造一下,不知道时间够不,先试一试在说.之前设计数据库用的Power ...

  3. 计蒜客 39270.Angel's Journey-简单的计算几何 ((The 2019 ACM-ICPC China Shannxi Provincial Programming Contest C.) 2019ICPC西安邀请赛现场赛重现赛

    Angel's Journey “Miyane!” This day Hana asks Miyako for help again. Hana plays the part of angel on ...

  4. Luogu5206 【WC2019】数树 【容斥,生成函数】

    题目链接 第一问白给. 第二问: 设 \(b=y^{-1}\),且以下的 \(Ans\) 是除去 \(y^n\) 的. 设 \(C(T)\) 是固定了 \(T\) 中的边,再连 \(n-|T|-1\) ...

  5. Noip2019暑期训练1

    题目名称 时空定位 棋子移动 高精度乘法 数独游戏 存盘文件名 location piece mul sudoku 输入文件名 location.in piece.in mul.in sudoku.i ...

  6. ASCII编码(以备不时之需)

  7. debian10使用国内源安装docker以及一些使用方法

    首先, 我的环境是debian, 容器是centos debian 安装添加新存储库所需的依赖项 1 sudo apt install ca-certificates curl software-pr ...

  8. Symfony之入门学习

    最近因业务需要,主要针对Edusoho进行二次开发.但是对于Symfony,我并不熟悉,我所了解的是,它的那套与我在Java中常用的开发模式MVC,本质上并不多大差异,就是所使用的语言不一样而已.下面 ...

  9. 2D转换模块

    2D转换模块(transform) 1.取值:rotate(45deg)--- 旋转,默认以自己为中心作为参考点来旋转 .translate(100px,0px)--- 平移,第一个参数代表水平方向, ...

  10. AOP通知类型

    AOP通知类型 前置通知 在目标方法执行之前进行操作 后置通知 在目标方法执行之后 进行操作 环绕通知 在目标方法执行之前 和之后进行操作 public Object arount() 异常抛出通知 ...