uva 10458 - Cricket Ranking(容斥+高精度)

题目连接:uva 10458 - Cricket Ranking

题目大意:给定k和n,表示有k个比赛,总共要的n分,每个比赛可以得l~r的分数,问说可以有多少种得分方式。

解题思路:容斥,可以参考Codeforces 451E.

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
typedef long long ll;
const int MAXN = 1005;

struct bign {
    int len;
    ll num[MAXN];

    bign () {
        len = 0;
        memset(num, 0, sizeof(num));
    }
    bign (ll number) {*this = number;}
    bign (const char* number) {*this = number;}

    void DelZero ();
    void Put ();

    void operator = (ll number);
    void operator = (char* number);

    bool operator <  (const bign& b) const;
    bool operator >  (const bign& b) const { return b < *this; }
    bool operator <= (const bign& b) const { return !(b < *this); }
    bool operator >= (const bign& b) const { return !(*this < b); }
    bool operator != (const bign& b) const { return b < *this || *this < b;}
    bool operator == (const bign& b) const { return !(b != *this); }

    void operator ++ ();
    void operator -- ();
    bign operator + (const int& b);
    bign operator + (const bign& b);
    bign operator - (const int& b);
    bign operator - (const bign& b);
    bign operator * (const ll& b);
    bign operator * (const bign& b);
    bign operator / (const ll& b);
    //bign operator / (const bign& b);
    int operator % (const int& b);
};

/*Code*/
const int maxn = 10;
ll k, n, s, l[maxn], r[maxn];

void init () {
    s = 0;
    for (int i = 0; i < k; i++) {
        scanf("%lld%lld", &l[i], &r[i]);
        r[i] -= l[i];
        n -= l[i];
        s += r[i];
    }
}

bign C (ll u, ll v) {

    v = min(v, u-v);

    bign ans = 1;
    for (ll i = 0; i < v; i++)
        ans = ans * (u-i) / (i+1);
    return ans;
}

void solve () {
    if (n < 0 || n > s) {
        printf("0\n");
        return ;
    }

    bign add = 0LL, del = 0LL;

    for (int i = 0; i < (1<<k); i++) {
        ll sum = 0, cnt = 0;
        for (int j = 0; j < k; j++) {
            if (i&(1<<j)) {
                cnt++;
                sum += (r[j] + 1);
            }
        }

        if (n < sum)
            continue;

        if (cnt&1)
            del = del + C(n-sum+k-1, k-1);
        else
            add = add + C(n-sum+k-1, k-1);
    }

    if (add < del) {
        printf("0\n");
        printf("\n");
    }

    /*
    add.Put();
    printf("\n");
    del.Put();
    printf("\n");
    */
    bign ans = add - del;
    bign rec = ans + del;

    while (add != rec);

    ans.Put();
    printf("\n");
}

int main () {
    while (scanf("%lld%lld", &k, &n) == 2) {
        init ();
        solve();
    }
    return 0;
}
/*********************************************/

void bign::DelZero () {
    while (len && num[len-1] == 0)
        len--;

    if (len == 0) {
        num[len++] = 0;
    }
}

void bign::Put () {
    for (int i = len-1; i >= 0; i--)
        printf("%lld", num[i]);
}

void bign::operator = (char* number) {
    len = strlen (number);
    for (int i = 0; i < len; i++)
        num[i] = number[len-i-1] - ‘0‘;

    DelZero ();
}

void bign::operator = (ll number) {

    len = 0;
    while (number) {
        num[len++] = number%10;
        number /= 10;
    }

    DelZero ();
}

bool bign::operator < (const bign& b) const {
    if (len != b.len)
        return len < b.len;
    for (int i = len-1; i >= 0; i--)
        if (num[i] != b.num[i])
            return num[i] < b.num[i];
    return false;
}

void bign::operator ++ () {
    int s = 1;

    for (int i = 0; i < len; i++) {
        s = s + num[i];
        num[i] = s % 10;
        s /= 10;
        if (!s) break;
    }

    while (s) {
        num[len++] = s%10;
        s /= 10;
    }
}

void bign::operator -- () {
    if (num[0] == 0 && len == 1) return;

    int s = -1;
    for (int i = 0; i < len; i++) {
        s = s + num[i];
        num[i] = (s + 10) % 10;
        if (s >= 0) break;
    }
    DelZero ();
}

bign bign::operator + (const int& b) {
    bign a = b;
    return *this + a;
}

bign bign::operator + (const bign& b) {
    int bignSum = 0;
    bign ans;

    for (int i = 0; i < len || i < b.len; i++) {
        if (i < len) bignSum += num[i];
        if (i < b.len) bignSum += b.num[i];

        ans.num[ans.len++] = bignSum % 10;
        bignSum /= 10;
    }

    while (bignSum) {
        ans.num[ans.len++] = bignSum % 10;
        bignSum /= 10;
    }

    return ans;
}

bign bign::operator - (const int& b) {
    bign a = b;
    return *this - a;
}

bign bign::operator - (const bign& b) {
    ll bignSub = 0;
    bign ans;
    for (int i = 0; i < len || i < b.len; i++) {
        bignSub += num[i];
        if (i < b.len)
            bignSub -= b.num[i];
        ans.num[ans.len++] = (bignSub + 10) % 10;
        if (bignSub < 0) bignSub = -1;
        else bignSub = 0;
    }
    ans.DelZero();
    return ans;
}

bign bign::operator * (const ll& b) {
    ll bignSum = 0;
    bign ans;

    ans.len = len;
    for (int i = 0; i < len; i++) {
        bignSum += num[i] * b;
        ans.num[i] = bignSum % 10;
        bignSum /= 10;
    }

    while (bignSum) {
        ans.num[ans.len++] = bignSum % 10;
        bignSum /= 10;
    }

    return ans;
}

bign bign::operator * (const bign& b) {
    bign ans;
    ans.len = 0; 

    for (int i = 0; i < len; i++){
        int bignSum = 0;  

        for (int j = 0; j < b.len; j++){
            bignSum += num[i] * b.num[j] + ans.num[i+j];
            ans.num[i+j] = bignSum % 10;
            bignSum /= 10;
        }
        ans.len = i + b.len;  

        while (bignSum){
            ans.num[ans.len++] = bignSum % 10;
            bignSum /= 10;
        }
    }
    return ans;
}

bign bign::operator / (const ll& b) {

    bign ans;

    ll s = 0;
    for (int i = len-1; i >= 0; i--) {
        s = s * 10 + num[i];
        ans.num[i] = s/b;
        s %= b;
    }

    ans.len = len;
    ans.DelZero();
    return ans;
}

int bign::operator % (const int& b) {

    bign ans;

    int s = 0;
    for (int i = len-1; i >= 0; i--) {
        s = s * 10 + num[i];
        ans.num[i] = s/b;
        s %= b;
    }

    return s;
}

uva 10458 - Cricket Ranking(容斥+高精度),布布扣,bubuko.com

时间: 2024-10-12 08:58:07

uva 10458 - Cricket Ranking(容斥+高精度)的相关文章

UVA 10458 - Cricket Ranking(容斥原理)

UVA 10458 - Cricket Ranking 题目链接 题意:给定k个区间,要求用这些数字范围去组合成n,问有几种组合方式 思路:容斥原理,容斥是这样做:已知n个组成s,不限值个数的话,用隔板法求出情况为C(s + n - 1, n - 1),但是这部分包含了超过了,那么就利用二进制枚举出哪些是超过的,实现把s减去f(i) + 1这样就保证这个位置是超过的,减去这部分后,有多减的在加回来,这就满足了容斥原理的公式,个数为奇数的时候减去,偶数的时候加回 代码: #include <cst

uva 11123 - Counting Trapizoid(容斥+几何)

题目链接:uva 11123 - Counting Trapizoid 题目大意:给定若干个点,问有多少种梯形,不包括矩形,梯形的面积必须为正数.因为是点的集合,所以不会优重复的点. 解题思路:枚举两两点,求出该条直线,包括斜率k,偏移值c,以及长度l.已知梯形的性质,一对对边平行,也就是说一对平行但是不相等的边. 所以将所有线段按照斜率排序,假设对于某一斜率,有m条边,那么这m条边可以组成的含平行对边的四边形有C(2m),要求梯形还要减掉长度相同以及共线的情况,分别对应的是l相同和c相同,但是

uva 11806 Cheerleaders(容斥)

题意:如何摆放拉拉队的问题,在矩形网格m*n中,k名拉拉队员,要求四周网格中each side有至少一名拉拉队员,corner有人算两边,问有多少种摆法? 思路:容斥: c[m*n][k] -- c[(n-1)*m][k] U c[(n-1)*m][k] U c[n*(m-1)][k] U c[n*(m-1)][k] #include<cstdio> #include<iostream> #include<cstring> #define mod 1000007 usi

POJ2103 Jackpot(容斥+高精度)

Jackpot Time Limit: 20000MS   Memory Limit: 64000K Total Submissions: 1044   Accepted: 216 Case Time Limit: 2000MS Description The Great Dodgers company has recently developed a brand-new playing machine. You put a coin into the machine and pull the

uva 10542 - Hyper-drive(容斥)

题目链接:uva 10542 - Hyper-drive 题目大意:给定n维空间的线段,问说线段经过几个格子. 解题思路:对于线段可以将一点移动至原点,变成 (0,0)到(a,b)这条线段,以二维为例,每次会从一个格子移动到另一个格子,可以是x+1坐标,也可以是y+1,所以总的应该是a+b-1,扣除掉x+1,y+1的情况gcd(a,b)-1 (原点).映射成n维就要用容斥原理计算结果. /*********************** * (0, 0, 0, ...) -> (a, b, c,

UVA 11123 - Counting Trapizoid(计数问题+容斥)

UVA 11123 - Counting Trapizoid 题目链接 题意:给定一些点,不重复,求出一共有几个梯形 思路:先把所有两点组成直线求出来,然后排序,斜率相同的C2n个,然后再扣除掉重叠的直线情况和长度相等情况(这样为平行四边形或矩形),由于扣除的时候会重复扣掉重叠和相等,所以在加回来,这是容斥原理. 代码: #include <stdio.h> #include <string.h> #include <math.h> #include <algor

UVA 11806 组合数学+容斥

UVA: https://vjudge.net/problem/UVA-11806 题意:给你一个n×mn×m的矩阵网格和kk个人,问有多少种方法使得每一个格子只放一个人,并且第一行,最后一行,第一列,最后一列都有人.直接枚举似乎有难度,我们考虑容斥.rr行cc列放kk个人的方案数是(r×ck)(r×ck),那么由容斥原理,总方案为 ans=U?A?B?C?D+AB+AC+AD+-+ABCDans=U?A?B?C?D+AB+AC+AD+-+ABCD 其中UU表示没有限制的方案数,A,B,C,DA

hdu_5768_Lucky7(中国剩余定理+容斥)

题目链接:hdu_5768_Lucky7 题意: 给你一个区间,问你这个区间内是7的倍数,并且满足%a[i]不等于w[i]的数的个数 乍一看以为是数位DP,仔细看看条件,发现要用中国剩余定理,然后容斥一下就出答案了,不过这里在中国剩余定理里面的乘法会有数据爆long long ,所有要写一个高精度乘法,这里卡死很多人. 1 #include <bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace

POJ 2773 Happy 2006 二分+容斥(入门

题目链接:点击打开链接 题意: 输入n ,k 求与n互质的第k个数(这个数可能>n) 思路: solve(mid)表示[1,mid]中有多少个和n互质,然后二分一下最小的mid 使得互质个数==k solve(x) 实现: 与n互质的个数=所有数-与n不互质的数=所有数-(与n有一个因子-与n有2个因子的+与n有3个因子的) 状压n的因子个数,然后根据上面的公式容斥得到. #include <stdio.h> #include <iostream> #include <