absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] 国家集训队作业计划
[破碎的状态] ARC063E

[破碎的状态] AGC12D

absi2011 posted @ Oct 18, 2017 06:16:23 PM in 刷题记录 with tags 小高考 瞎搞 集训队作业 atcoder , 473 阅读

link:http://agc012.contest.atcoder.jp/tasks/agc012_d

题意:

给你n个球

每个球有一个颜色(c)和一个权值(w)

如果两个同色球的权值和<=X可以交换它们

如果两个异色球的权值和<=Y可以交换它们

问:你最多可以交换出多少种颜色排列?

例如:三个同色球,不管X,Y,w是多少答案都是1,

1<=c<=n

n<=200000

解法:

如果a和b可以交换,a和c可以交换

那么a和c也可以交换

a b c --> b a c --> c a b --> c b a

那么就好了么..

每个球,和同色的w最小值可不可以互换?

和异色的w最小值可不可以互换?

如果都不可以你就呆那边吧.......

如果可以和同色换,同色最小值和异色可不可以互换?

如果不可以也呆那边吧,这个颜色没啥意义.....

然后就是...不同颜色之间互相换....实际上就是个组合数的问题了..

代码:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<math.h>
#include<time.h>
#include<vector>
#include<bitset>
#include<memory>
#include<utility>
#include<fstream>
#include<stdio.h>
#include<sstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
int c[200005];
int w[200005];
int min_num[200005];
int sum[200005];
const int modo=1000000007;
int fact[200005];
int anti_fact[200005];
int c_(int x,int y)
{
    return (long long)fact[x]*anti_fact[y]%modo*anti_fact[x-y]%modo;
}
int power(int x,int y)
{
    if (y==0) return 1;
    int t=power(x,y/2);
    t=(long long)t*t%modo;
    if (y%2==1) t=(long long)t*x%modo;
    return t;
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,x,y;
    scanf("%d%d%d",&n,&x,&y);
    int i;
    for (i=0;i<n;i++)
    {
        min_num[i]=1099999999;
    }
    fact[0]=1;
    anti_fact[0]=1;
    for (i=1;i<=200000;i++)
    {
        fact[i]=(long long)fact[i-1]*i%modo;
        anti_fact[i]=power(fact[i],modo-2);
    }
    for (i=0;i<n;i++)
    {
        scanf("%d%d",&c[i],&w[i]);
        c[i]--;
        min_num[c[i]]=min(min_num[c[i]],w[i]);
    }
    int min1=0,min2=0;
    for (i=0;i<n;i++)
    {
        if (min_num[min1]>min_num[i])
        {
            min1=i;
        }
    }
    if (min1==0) min2=1;
    for (i=0;i<n;i++)
    {
        if (i==min1) continue;
        if (min_num[min2]>min_num[i])
        {
            min2=i;
        }
    }
    int tot=0;
    for (i=0;i<n;i++)
    {
        if (c[i]==min1)
        {
            if (w[i]+min_num[min2]<=y)
            {
                tot++;
                sum[c[i]]++;
                continue;
            }
            else if (w[i]+min_num[min1]<=x)
            {
                tot++;
                sum[c[i]]++;
                continue;
            }
        }
        else
        {
            if (w[i]+min_num[min1]<=y)
            {
                tot++;
                sum[c[i]]++;
                continue;
            }
            else if ((w[i]+min_num[c[i]]<=x)&&(min_num[c[i]]+min_num[min1]<=y))
            {
                tot++;
                sum[c[i]]++;
                continue;
            }
        }
    }
    int p=1;
    for (i=0;i<n;i++)
    {
        p=(long long)p*c_(tot,sum[i])%modo;
        tot-=sum[i];
    }
    printf("%d\n",p);
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter