Uva 12906——Maximum Score

题意:定义数组的分数是sigma C[i],其中C[i]是第i个数左边最大的递增子序列和第i个数右边最大的递减子序列的长度和。给定一个集合,求这个集合的全排列中最大的分数,并求出得到这个最大分数的方法种数。
思路:假设说有一个集合中,数字t的个数是最多的,有m个。那么分数最高的方法就是将这个t充分利用。根据规则,最好就是比t大的都在t的一边,比t小的都在t的一边。这样就分析得到这个数组是一个有序的数组时分数最高。所以,只需要将数组排序就可以了。
对于方法种数。通过举例子可以得到,当这个数组最大的一个数左边是递增的,右边是递减的时候,也可以得到最大的分数。所以方法种数就是这个数组先递增后递减的排列的方法数。将最小的数字固定,把较大的数字往里面插入就好了。
代码如下:

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<map>
#include<cmath>
#include<assert.h>
using namespace std;
typedef long long ll;

const ll mod = 1000000007;

struct Per
{
    int v,f;
    bool operator < ( const Per &a) const {
        return v<a.v;
    }
};

Per per[100005];
unsigned long long cnt[100005];

int main()
{
//    freopen("data.txt","r",stdin);
    int T;
    scanf("%d",&T);
    int kase=0;
    while(T--){
        printf("Case %d: ",++kase);
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            scanf("%d%d",&per[i].v,&per[i].f);
        }
        sort(per,per+n);
        cnt[0]=per[0].f;
        for(int i=1;i<n;++i){
            cnt[i]=cnt[i-1]+per[i].f;
        }
        unsigned long long ans=0;
        for(int i=0;i<n;++i){
            ans=ans+cnt[i]*per[i].f;
        }
        ll t = 1;
        for(int i=0;i<n-1;++i){
            t=t*(per[i].f+1)%mod;
        }
        cout<<ans<<' '<<t<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值