2018 ACM-ICPC 中国大学生程序设计竞赛线上赛-D:Merchandise(单调栈优化DP)

Description:

The elderly aunts always like to look for bargains and preferential merchandise. Now there is a shop carrying out group purchase promotion. 

Rules are as follows : 

There are r pieces of promotional items, and each item is only one. In the group purchase, everyone will buy one at least and have to conform the rules if they want to enjoy the benefit :

All the merchandise at a prime number has to be purchased ; 

the merchandise at non-prime number cannot be chosen ; 

The amount of money that each person pays is the square of the difference between the maximum and minimum value of the product he or she chooses. Notice that there may be several merchandises having the same price.

(If a person buys only one item, follow the rules and spend ¥ 0.00)

Assume that there are m people in a group, and everyone should enjoy the benefit.  Please arrange each person's choice of merchandise reasonably, so that the sum of money paid by m people can be the minimum. 

The number of merchandise with a price of prime is n,m<=n , n<=5000

Input:

The input contains multiple test cases.

In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given. 

 For any test case, the first line of input consists of two separated integers r and m.

(0<r<=100000,0<m<=1000)

The second line should consists of r space separated integers k1,k2...kr.

(1<ki<2^16,1<=i<=r)

ki represents the price of one item 

Output:

Print one integer sum (sum<2^32)——the minimum number of money paid by m people.

样例输入

1
6 2
5 6 10 2 11 3 

样例输出

9

题目来源

2018 ACM-ICPC 中国大学生程序设计竞赛线上赛

思路:将所有质数分为m组,把所有质数排序后,那么肯定是将连续的质数分为一组更优。d[i][j]表示前i个数分为j组的最小代价。d[i][j]=d[k-1][j-1]+a[i]*a[i]-2*a[i]*a[k]+a[k]*a[k]。那么这样一看就是经典的斜率优化DP了。

d[k-1][j-1]+a[k]*a[k]=a[i]*2*a[k]+d[i][j]-a[i]*a[i]。(y=k*x+b)

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
int all=0,pr[MAX+100];
int isp[MAX+10];
ll d[7000][1010],a[MAX];
ll X[MAX],Y[MAX];
void init()
{
	all = 0;
	memset(isp,0,sizeof isp);
	isp[1]=0;
	for(int i=2;i<=MAX;i++)
	{
		if(!isp[i])pr[all++] = i;
		for(int j=0;j<all;j++)
		{
			long long t = 1LL*pr[j]*i ;
			if(t<=MAX)
			{
				isp[t] = 1;
				if(i%pr[j]==0)break;
			}
			else break;
		}
	}
	return ;
}
int main()
{
    init();
    int T;
    cin>>T;
    while(T--)
    {
        int len,m,n=0;
        scanf("%d%d",&len,&m);
        for(int i=1;i<=len;i++)
        {
            int x;
            scanf("%d",&x);
            if(isp[x]==0)a[++n]=x;//本题中0,1也算作质数
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++)d[i][1]=(a[i]-a[1])*(a[i]-a[1]);
        int L,R;
        for(int j=2;j<=m;j++)
        {
            L=R=0;
            Y[0]=a[j]*a[j];
            X[0]=2*a[j];
            for(int i=j;i<=n;i++)
            {
                while(L<R&&Y[L]-X[L]*a[i]>=Y[L+1]-X[L+1]*a[i])L++;
                d[i][j]=Y[L]-X[L]*a[i]+a[i]*a[i];
                ll y=d[i][j-1]+a[i+1]*a[i+1];
                ll x=2*a[i+1];
                while(R>L&&(y-Y[R-1])*(x-X[R])-(x-X[R-1])*(y-Y[R])>=0)R--;
                X[R+1]=x;
                Y[R+1]=y;
                R++;
            }
        }
        printf("%lld\n",d[n][m]);
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/mitsuha_/article/details/80266562