BestCoder Round #76 (div.2) 1001 & 1002

前两题A得还挺快,终于分数又涨了一些。。。第三题求出了全部连通集的个数,才发现让求的是全部连通集的大小之和,怎么求大小之和还没想到。ios

1001 DZY Loves Balls 这道题让求出A大于B的几率,可是题目自己好像和几率关系不大,我见过让求指望之类的几率题目,好像都比这个难一些。 一共N个球,取两个,一共的取法是N * (N-1),这里是把值相同的球也看作不一样来想。 求A大于B的状况的种类,咱们能够对这N个值作一个筒排序,从小到大扫描,就能在线性复杂度内求出每一个值的球,比它小的有多少个球,累加这些值就好。spa

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int s[320];
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        memset(s, 0, sizeof(s));
        int n, a;
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &a);
            s[a]++;
        }
        int presum = 0, p = 0;
        for(int i = 1; i <= 300; i++)
        {
            if(s[i]) p += s[i] * presum;
            presum += s[i];
        }
        int q = n*(n-1);
        double ans = (double)p / q;
        printf("%.6f\n", ans);
    }
    return 0;
}

1002 DZY Loves Partition 把n分解成k个不一样的数的和,求这k个不一样的数的最大乘积是多少。 若是n小于1到k的累和((1+k) * k / 2),那么确定是无解的。code

若是n大于等于k,咱们能够将n想象成从1加到k再加剩余的部分(n-sum(1,k)),咱们只要把剩余的值想办法加到1到k的一些数中,知足最大乘积最大就好。排序

好比n = 30,k = 7: 1 + 2 + 3 + 4 + 5 + 6 + 7 这不够n,还差2,咱们将2加到某些数上就好。 咱们将后2个数向后移一位是最划得来的,由于1到5不能移动(加2也不会超过7,这样会重复),6+2=8和7+1=8且6+1=7是同样的。ci

其实就是一个贪心策略,咱们总让靠右边的数优先加上1(即向右移动),再证实若是左边的数加上某值获得的结果不会比先前的策略好。string

#include <cstdio>
#include <iostream>
using namespace std;
typedef long long lint;
const int mod = 1000000007;
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        lint n, k;
        cin >> n >> k;
        lint l = ((1 + k) * k) / 2;
        if(n < l)
        {
            printf("-1\n");
            continue;
        }
        lint a = 1, b = k;
        lint res = n - l;
        a += (res / k);
        b += (res / k);
        res %= k;
        lint ans = 1;
        lint o = b;
        while(o >= a)
        {
            if(res)
            {
                ans *= (o+1);
                res--;
            }
            else
            {
                ans *= o;
            }
            ans %= mod;
            o--;
        }
        cout << ans << endl;
    }
    return 0;
}

代码很简单,注意到若是n-sum(1, k)剩下的值很大的话能够除以n,获得的商加到每一个数上,这样咱们只须要记录k个值的两个端点就好。it

相关文章
相关标签/搜索