[Weekend training] journey

topic

[Memory Limit: $ 256MiB $] [Time limit: $ 1000ms $]

[Title] [standard input and output types: traditional] [ Evaluation method: Text Comparison]


 

Description [title]

$ Pine $ start from $ S $ to $ T $ to journey land.

From $ S $ to $ T $ to the road can be divided into $ N $ section, a demarcation point adjacent the road is provided with two rest stop.

$ Pine $ $ M $ with a plan to reach $ T $-day places. In addition to the first $ M $ day, every night $ Pine $ must overnight rest stop. Therefore, the section of the road to be completed in the same day.

$ Pine $ hope every day go the way of similar length as much as possible, so he hoped that the variance of the length of the road every day to go as small as possible.

Help $ Pine $ value of minimum variance is.

Provided variance V $ $ , can be shown, $ v × M ^ 2 $ is an integer. To avoid precision error, the output result output $ V ^ 2 × M $ .

[Input Format]

The first two row number $ N, M $

$ N $ second line number, $ N $ denotes the length of the road segment.

[Output format]

A number, minimum variance multiplied by $ M ^ 2 $ value after.

[Sample]

Sample input

5 2
1 2 5 8 6

Sample Output

36

[Note] with the data range

For $ 30 \% $ data, $ 1 \ leq N \ leq 10 $
For $ 60 \% $ data, $. 1 \ Leq N \ $ 100 Leq
For $ 100 \% $ data, $. 1 \ Leq N \ Leq $ 3000 .
Guarantee from $ S $ to $ T $ of the total distance of not more than $ 30,000 $ .

answer

[Experience] do title

After finding the key to this question, I called the $ DP $ naked, on top of the results card initialization, and later found the bare $ DP $ available $ 80pts $

[Correct]

Looked at the problem, we seek to find the topic of how things did not seem to clear, then we should first manually or simplified formula is something about the topic given $ v * M ^ 2 $.

First, we set the title of the number $ N $ $ a_1, a_2 ...... a_N $ in some way by the combination of the number becomes $ M $ $ x_1, x_2 ...... x_M $ .

令$S=\sum_{i=1}^{M}x_i$

By then the variance formula available

$$v=\frac{\sum_{i=1}^{M}(x_i-\frac{S}{M})}{M}$$

Expanded by squaring difference formula, available

$$v=\frac{\sum_{i=1}^{M}({x_i}^2+\frac{S^2}{M^2}-2x_i\frac{S}{M})}{M}$$

And we ask for is $ v × M ^ 2 $, do not forget that $ M ^ 2 $, will now be $ M ^ 2 $ ride in, available

$$v*M^2=M\cdot \sum_{i=1}^{M}({x_i}^2+\frac{S^2}{M^2}-2x_i\frac{S}{M})$$

The open brackets, available

$$vM^2=M\sum_{i=1}^{M}{x_i}^2+M^2\frac{S^2}{M^2}-2M\frac{S}{M}\sum_{i=1}^{M}x_i$$

Because $ S = \ sum_ {i = 1} ^ {M} x_i $, so we can simplify the equation, available

$$vM^2=M\sum_{i=1}^{M}{x_i}^2+S^2-2S^2$$

Finally, you can get

$$v×M^2=M\sum_{i=1}^{M}{x_i}^2-S^2$$

In the formulas, $ M $ and $ S $ are known, we can only make the biggest part of the sum.

Then start $ DP $: Order

$ Dp [j] [i] $: $ before the number of $ I $ $ a_i composition to the maximum summing the squares of the $ $ $ x_j number J $ $ x_j $.

$ S [i] $: prefixes and are not explained.

Then there is shaped turn $$ dp [j] [i] = max \ {dp [j-1] [k] + (s [i] -s [k]) ^ 2 | k \ in [0, i- 1] \} $$

Then we can code a $ 80pts $ code:

 

#include<bits/stdc++.h>
using namespace std;
#define int long long
template<class T>inline void qread(T& x){
    char c;bool f=false;x=0;
    while((c=getchar())<'0'||'9'<c)if(c=='-')f=true;
    for(x=(c^48);'0'<=(c=getchar())&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x; 
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
inline int rqread(){
    char c;bool f=false;int x=0;
    while((c=getchar())<'0'||'9'<c)if(c=='-')f=true;
    for(x=(c^48);'0'<=(c=getchar())&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
const int MAXN=3000;
int N,M,a[MAXN+5],s[MAXN+5],dp[MAXN+5][MAXN+5];
signed main(){
    qread(N,M);
    for(int i=1;i<=N;++i)s[i]=s[i-1]+(a[i]=rqread());
    memset(dp,0x3f,sizeof dp);dp[0][0]=0;
    for(int j=1;j<=M;++j)for(int i=1;i<=N;++i)for(int k=0;k<i;++k)
        dp[j][i]=Min(dp[j-1][k]+(s[i]-s[k])*(s[i]-s[k]),dp[j][i]);
    printf("%lld\n",M*dp[M][N]-s[N]*s[N]);
    return 0;
}

 

This is a bare $ $ the DP, which can be found in time complexity is $ O (NM ^ 2) $, $ N $, for a maximum is $ 3000 $, or will time out.

Consider for optimization, look at the form, the form found $ f (x) = max \ {g (x) \} + tmp $, then the time we will slope to optimize it.

Then, a dimension can be ripped off the hard, final time complexity is $ O (NM) $, code is as follows:

 

#include<bits/stdc++.h>
using namespace std;
#define int long long
template<class T>inline void qread(T& x){
    char c;bool f=false;x=0;
    while((c=getchar())<'0'||'9'<c)if(c=='-')f=true;
    for(x=(c^48);'0'<=(c=getchar())&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x; 
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
inline int rqread(){
    char c;bool f=false;int x=0;
    while((c=getchar())<'0'||'9'<c)if(c=='-')f=true;
    for(x=(c^48);'0'<=(c=getchar())&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
const int MAXN=3000;
const int BUFFER_SIZE=3000;
int N,M,a[MAXN+5],s[MAXN+5],dp[MAXN+5][MAXN+5];
int Q[BUFFER_SIZE+5],head,tail;
inline void init(){head=1,tail=0;}
inline double calc(const int j,const int k,const int l){return (dp[j-1][k]-dp[j-1][l]+s[k]*s[k]-s[l]*s[l])*1.0/(s[k]-s[l]);}
inline int getDp(const int j,const int i,const int k){return dp[j-1][k]+(s[i]-s[k])*(s[i]-s[k]);}
signed main(){
    qread(N,M);
    memset(dp,0x3f,sizeof dp);dp[0][0]=0;
    for(int i=1;i<=N;++i)s[i]=s[i-1]+(a[i]=rqread()),dp[1][i]=s[i]*s[i];
    for(int j=2;j<=M;++j){
        init();
        for(int i=1;i<=N;++i){
            while(head<tail&&calc(j,Q[head],Q[head+1])<2.0*s[i])++head;
            dp[j][i]=getDp(j,i,Q[head]);
            while(head<tail&&calc(j,Q[tail-1],Q[tail])>calc(j,Q[tail],i))--tail;
            Q[++tail]=i;
        }
    }
    printf("%lld\n",M*dp[M][N]-s[N]*s[N]);
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/MachineryCountry/p/11627614.html