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

相關文章
相關標籤/搜索