AtCoder:Colorful Balls(思维 & 数论)

D - Colorful Balls


Time limit : 2sec / Memory limit : 256MB

Score : 1000 points

Problem Statement

Snuke arranged N colorful balls in a row. The i-th ball from the left has color ci and weight wi.

He can rearrange the balls by performing the following two operations any number of times, in any order:

  • Operation 1: Select two balls with the same color. If the total weight of these balls is at most X, swap the positions of these balls.
  • Operation 2: Select two balls with different colors. If the total weight of these balls is at most Y, swap the positions of these balls.

How many different sequences of colors of balls can be obtained? Find the count modulo 109+7.

Constraints

  • 1N2×105
  • 1X,Y109
  • 1ciN
  • 1wi109
  • X,Y,ci,wi are all integers.

Input

Input is given from Standard Input in the following format:

N X Y
c1 w1
:
cN wN

Output

Print the answer.


Sample Input 1

Copy
4 7 3
3 2
4 3
2 1
4 4

Sample Output 1

Copy
2
  • The sequence of colors (2,4,3,4) can be obtained by swapping the positions of the first and third balls by operation 2.
  • It is also possible to swap the positions of the second and fourth balls by operation 1, but it does not affect the sequence of colors.

Sample Input 2

Copy
1 1 1
1 1

Sample Output 2

Copy
1

Sample Input 3

Copy
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 v
3 7
12 41
13 88
18 6
2 12
13 87
1 9
2 27
13 15

Sample Output 3

Copy
129729600
题意:给N个球的颜色ci和权值wi,对于相同颜色的球,权值和<=x,或者不同颜色的球权值和<=y都可以交换,不限交换次数,问组成的颜色序列数有多少种。

思路:对于不同颜色的三个球a,b,c,如果a和b能换,b和c能换,那么a和c一定能换,因为abc->acb->bca->cba,于是找到最小权值的球,建边,就变成有重复元素的组合数问题了,用乘法逆元可以解决。

# include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 2e5+3;

LL fac[maxn], inv[maxn];
int cnt, n, x, y, co[maxn], va[maxn], vis[maxn]={0}, ge[maxn]={0};
vector<int>v[maxn], tmp;
vector<pair<int, int> >r[maxn];
vector<pair<int, int> >p;

void dfs(int u)
{
    vis[u] = 1;
    ++cnt, ++ge[co[u]], tmp.push_back(co[u]);
    for(int i=0; i<v[u].size(); ++i)
    {
        int e = v[u][i];
        if(vis[e]) continue;
        dfs(e);
    }
}
int main()
{
    int c, w;
    scanf("%d%d%d",&n,&x,&y);
    cnt = 0;
    fac[0] = fac[1] = inv[0] = inv[1] = 1;
    for(LL i=2; i<=n; ++i)
    {
        fac[i] = fac[i-1]*i%mod;
        inv[i] = (mod-mod/i)*inv[mod%i]%mod;
    }
    for(int i=2; i<=n; ++i)
        inv[i] = inv[i-1]*inv[i]%mod;
    for(int i=1; i<=n; ++i)
    {
        scanf("%d%d",&c,&w);
        co[i] = c, va[i] = w;
        r[c].push_back(make_pair(w, i));
    }
    for(int i=1; i<=n; ++i)
    {
        if(r[i].size())
        {
            sort(r[i].begin(), r[i].end());
            p.push_back(r[i][0]);
            for(int j=1; j<r[i].size(); ++j)
                if(r[i][j].first+r[i][0].first <= x)
                    v[r[i][0].second].push_back(r[i][j].second),
                    v[r[i][j].second].push_back(r[i][0].second);
        }
    }
    sort(p.begin(), p.end());
    if(p.size())//用权值最小的球为中介建图。
    {
        int id = p[0].second;
        for(int i=1; i<=n; ++i)
        {
            if(co[i]==co[id] || va[i]+va[id]>y) continue;
            v[id].push_back(i), v[i].push_back(id);
        }
    }
    if(p.size()>1)//该颜色的其他球也要考虑进去。
    {
        int id = p[1].second, imin = co[p[0].second];
        for(auto it = r[imin].begin(); it!=r[imin].end(); ++it)
            if(it->first + va[id]<=y)
                v[it->second].push_back(id), v[id].push_back(it->second);
    }
    dfs(p[0].second);
    LL ans = fac[cnt];
    for(int i=0; i<tmp.size(); ++i)
    {
        int num = ge[tmp[i]];
        ans = (ans*inv[num])%mod;
        ge[tmp[i]] = 0;
    }
    printf("%lld\n",ans);
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值