ZOJ-3447---Doraemon's Number Game (贪心+大数)

Doraemon's Number Game

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Doraemon and Nobita are playing a number game. First, Doraemon will give Nobita N positive numbers. Then Nobita can deal with these numbers for two rounds. Every time Nobita can delete i (2 ≤ iK) numbers from the number set. Assume that the numbers deleted is a[ 1 ], a[ 2 ] ... a[ i ]. There should be a new number X = ( a[ 1 ] * a[ 2 ] * ... * a[ i ] + 1 ) to be inserted back into the number set. The operation will be applied to the number set over and over until there remains only one number in the set. The number is the result of round. Assume two results A and B are produced after two rounds. Nobita can get |A - B| scores.

Now Nobita wants to get the highest score. Please help him.

Input

Input will contain no more than 10 cases. The first line of each case contains two positive integers N and K (1 ≤ N ≤ 100, 1 ≤ K ≤ 50). The following line contains N positive integers no larger than 50, indicating the numbers given by Doraemon.

Output

For each case, you should output highest score in one line.

Sample Input
6 3
1 3 4 10 7 15
Sample Output
5563
Hint

For most cases, N ≤ 20


题意:给出n和k,有n个数字,从中选择2~k删掉,然后将删掉的数的乘积加1加进去,求算得的最大值与最小值的差;

思路:很明显的贪心,求得最大值的策略是每次选取其中最小的两个数求积,求的最小值的策略是每次取出前1~k大的值求积,这题会爆long long,所以要用大数;

样例解释:

     求最大值1,3,4,7,10,15 ---(1*3+1)---->4,4,7,10,15---(4*4+1)---->7,10,,15,17---(7*10+1)---->15,17,71---(15*17+1)---->71,256---(71*25+1)---->18177;

     求最小值1,3,4,7,10,15---(7*10*15+1)---->1,3,4,1051---(3*4*1051+1)---->1,12613----(1*12613+1)----->12614;

     ans=18177-12614=5563;

AC代码:(这个大数模板挺好的,可以带走~)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
using namespace std;
struct cmp1
{
    bool operator ()(string a,string b)
    {
        if(a.size()==b.size())
            return a<b;
        else
        {
            return a.size()<b.size();
        }
    }
};

struct cmp2
{
    bool operator ()(string a,string b)
    {
        if(a.size()==b.size())
            return a>b;
        else
        {
            return a.size()>b.size();
        }
    }
};

priority_queue<string,vector<string>,cmp1>   que1;//优先取出最大元素(优先队列不懂的请另查资料)

priority_queue<string,vector<string>,cmp2>  que2;//优先取出最小元素

string ans;

//********大数加法********//
string sum(string s1,string s2)
{
    if(s1.length()<s2.length())
    {
        string temp=s1;
        s1=s2;
        s2=temp;
    }
    int i,j;
    for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
    {
        s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));   //注意细节
        if(s1[i]-'0'>=10)
        {
            s1[i]=char((s1[i]-'0')%10+'0');
            if(i) s1[i-1]++;
            else s1='1'+s1;
        }
    }
    return s1;
}

//*******大数乘法**********//
string Mult(string s,int x)  //大数乘以整形数
{
    reverse(s.begin(),s.end());
    int cmp=0;
    for(int i=0;i<s.size();i++)
    {
        cmp=(s[i]-'0')*x+cmp;
        s[i]=(cmp%10+'0');
        cmp/=10;
    }
    while(cmp)
    {
        s+=(cmp%10+'0');
        cmp/=10;
    }
    reverse(s.begin(),s.end());
    return s;
}
string Multfa(string x,string y)
{
    string ans;
    for(int i=y.size()-1,j=0;i>=0;i--,j++)
    {
        string tmp=Mult(x,y[i]-'0');
        for(int k=0;k<j;k++)
            tmp+='0';
        ans=sum(ans,tmp);
    }
    return ans;
}

//*******大数减法*******//
string sub(string a,string b)
{
    string c;
    bool ok=0;
    int len1=a.length();
    int len2=b.length();
    int len=max(len1,len2);
    for(int i=len1;i<len;i++)
        a="0"+a;
    for(int i=len2;i<len;i++)
        b="0"+b;
    if(a<b)
    {
        string temp=a;
        a=b;
        b=temp;
        ok=1;
    }
    for(int i=len-1;i>=0;i--)
    {
        if(a[i]<b[i])
        {
            a[i-1]-=1;
            a[i]+=10;
        }
        char temp=a[i]-b[i]+'0';
        c=temp+c;
    }
    int pos=0;
    while(c[pos]=='0' && pos<len) pos++;
    if(pos==len) return "0";
    if(ok) return "-"+c.substr(pos);
    return c.substr(pos);
}

int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        string ss;
        for(int i=1;i<=n;i++)
        {
            cin>>ss;
            que1.push(ss);
            que2.push(ss);
        }
        int ans1,ans2;

        while(que1.size()>1)//求最小值
        {
            string _sum="1";
            for(int i=1;i<=k&&que1.size();i++)//注意队列为空就不能再取了
            {
                _sum=Multfa(_sum,que1.top());
                que1.pop();
            }
            string a="1";
            _sum=sum(_sum,a);
            que1.push(_sum);
        }
        while(que2.size()>1)//求最大值
        {
            string a=que2.top();que2.pop();
            string b=que2.top();que2.pop();
            string c=Multfa(a,b);
            a="1";
            c=sum(c,a);
            que2.push(c);
        }
        cout<<sub(que2.top(),que1.top())<<endl;
        que1.pop();//注意将两个优先队列清空
        que2.pop();
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值