1. 程式人生 > >hihoCoder挑戰賽31

hihoCoder挑戰賽31

content 順序 ide 應該 判斷 itl ++ 遞增 一行

#1595 : Numbers

時間限制:8000ms 單點時限:1000ms 內存限制:256MB

描述

給定n個整數常數c[1], c[2], ..., c[n]和一個整數k。現在需要給2k個整數變量x[1], x[2], ..., x[k], y[1], y[2], ..., y[k]賦值,滿足

(1)對於所有1 ≤ i ≤ k,都有x[i] ≤ y[i]。

(2)對於所有1 ≤ i ≤ n,都存在至少一個j (1 ≤ j ≤ k),使得x[j] ≤ c[i] ≤ y[j]。

求出S=(y[1] + y[2] + ... + y[k]) - (x[1] + x[2] + ... + x[k])的最小值。

輸入

第一行兩個整數n, k。(1 ≤ n, k ≤ 100000)
接下來n行,每行一個整數c[i]。 (-1000000000 ≤ c[i] ≤ 1000000000)

輸出

輸出一個整數表示S的最小值。

樣例解釋

x[1]=-5, y[1]=4,

x[2]=10, y[2]=10.

樣例輸入
5 2
-5
0
10
4
0
樣例輸出
9

首先,如果k≥n則可以零距離夾住每個c,此時答案為0。

當k<n時,只需將n個數字從小到大排序,去掉其中最長的k-1個間隔即可。

技術分享
#include<stdio.h>
#include<string
.h> #include<stdlib.h> long long c[100005], d[100005]; int cmp(const void * x, const void * y) { return *((long long *) x) > *((long long *) y); } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif int n, k; scanf("%d%d", &n, &k); for
(int i = 0; i < n; i++) { scanf("%lld", &c[i]); } if (k >= n) { printf("0\n"); return 0; } qsort(c, n, sizeof(long long), cmp); for (int i = 0; i < n - 1; i++) { d[i] = c[i + 1] - c[i]; } qsort(d, n - 1, sizeof(long long), cmp); long long ans = c[n - 1] - c[0]; for (int i = 1, j = n - 2; i < k; i++, j--) { ans -= d[j]; } printf("%lld\n", ans); return 0; }
View Code

#1596 : Beautiful Sequence

時間限制:11000ms 單點時限:1000ms 內存限制:256MB

描述

對於一個正整數列a[1], ... , a[n] (n ≥ 3),如果對於所有2 ≤ i ≤ n - 1,都有a[i-1] + a[i+1] ≥ 2 × a[i],則稱這個數列是美麗的。

現在有一個正整數列b[1], ..., b[n],請計算:將b數列均勻隨機打亂之後,得到的數列是美麗的概率P。

你只需要輸出(P × (n!))mod 1000000007即可。(顯然P × (n!)一定是個整數)

輸入

第一行一個整數n。 (3 ≤ n ≤ 60)
接下來n行,每行一個整數b[i]。 (1 ≤ b[i] ≤ 1000000000)

輸出

輸出(P × (n!))mod 1000000007。

樣例輸入
4
1
2
1
3
樣例輸出
8

滿足美麗性質的序列形狀為V字形,即先遞減後遞增,單調序列可以理解為左邊或右邊長度為0的V字形。

V字形最低點的數字一定是數列中最小的數字,把數列按從小到大的順序依次添加到兩端,只要保證每次添加時和該端最邊上的兩個數字滿足美麗性質,即可實現美麗數列的構造。

首先按從小到大的順序排序

令dp[i][j][k][l]為當前的數列最左邊的兩個的下標分別為ij,最右邊的兩個數字的下標分別為kl時的美麗數列個數。若i=j,表示右邊沒有了;若k=l,表示左邊沒有了。

可以通過一個四重循環ijkl實現狀態轉移,第一重表示當前要添加下標為i的數字,顯然,此時數列最左端或最右端的數字中一定有一個編號為i-1,用三重循環jkl枚舉另外三個數字。i-1在左邊或右邊分兩種情況,每種情況下各自可能將i添加到左邊或右邊,一共四次判斷,復雜度為O(n^4)。

再想一想的話,其實在循環i時,兩端的四個數字裏除了必定有一個i-1之外,i-2肯定也在其中,所以其實只用枚舉另外兩個數字就行了,這種情況下要寫八次判斷,復雜度為O(n^3),應該也是可以的,不過沒有試。

技術分享
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n;
long long dp[65][65][65][65], a[130];
int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%lld", &a[i]);
    }
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (a[i] > a[j]) {
                long long t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
        }
    }
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] == a[0]) {
            cnt++;
        }
    }
    for (int i = 1; i < n; i++) {
        a[i] = a[i + cnt - 1];
    }
    n = n - cnt + 1;
    memset(dp, 0, sizeof(dp));
    dp[0][0][0][0] = dp[0][1][0][1] = dp[1][0][1][0] = 1;
    for (int i = 2; i < n; i++) {
        for (int j = 0; j < i; j++) {
            for (int k = 0; k < i; k++) {
                for (int l = 0; l < i; l++) {
                    //dp[i-1,j,k,l]
                    if (i - 1 != j && k != l) {
                        if ((long long)(a[i] + a[j]) >= (long long)(2 * a[i - 1])) {
                            dp[i][i - 1][k][l] += dp[i - 1][j][k][l];
                            dp[i][i - 1][k][l] %= 1000000007;
                        }
                        if ((long long)(a[k] + a[i]) >= (long long)(2 * a[l])) {
                            dp[i - 1][j][l][i] += dp[i - 1][j][k][l];
                            dp[i - 1][j][l][i] %= 1000000007;
                        }
                    }
                    //dp[j,k,l,i-1]
                    if (j != k && l != i - 1) {
                        if ((long long)(a[i] + a[k]) >= (long long)(2 * a[j])) {
                            dp[i][j][l][i - 1] += dp[j][k][l][i - 1];
                            dp[i][j][l][i - 1] %= 1000000007;
                        }
                        if ((long long)(a[l] + a[i]) >= (long long)(2 * a[i - 1])) {
                            dp[j][k][i - 1][i] += dp[j][k][l][i - 1];
                            dp[j][k][i - 1][i] %= 1000000007;
                        }
                    }
                }
            }
        }
    }
    long long ans = 0;
    if (n > 1) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    ans += dp[n - 1][i][j][k];
                    ans += dp[i][j][k][n - 1];
                    ans %= 1000000007;
                }
            }
        }
    } else {
        ans = 1;
    }
    for (int i = 1; i <= cnt; i++) {
        ans = (ans * i) % 1000000007;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

hihoCoder挑戰賽31