中国石油大学ACM俱乐部开放训练赛

问题 A: sciorz画画

题目描述

众所周知,sciorz会画画。某天,sciorz画了一个凸多边形,这个多边形的每个顶点都有一个权值a[i]。sciorz觉得这个凸多边形不够美丽,于是他决定在n个点之间连线,最终用n-3条不相交的线将这个凸n边形分割成n-2个三角形。sciorz认为,一个三角形的美丽值是三个顶点权值的乘积,凸多边形的美丽值是其内部三角形的美丽值的和。sciorz想找到一种分割方案,使得这个凸多边形的美丽值最大。sciorz忙着刷难题,所以他随手就把这个签到题扔给你,希望你帮sciorz算出最大的美丽值。

输入

第一行一个t,表示有t组样例。
每组样例的第一行是一个n,表示多边形的边数。
第二行n个数,第i个数表示多边形第i个顶点的权值a[i],按逆时针顺序给出。

输出

对于每组样例,输出一行。格式为"Case #x: y",x为样例编号,y为答案。

样例输入 Copy

2
3
1 2 3 
4
1 2 3 4

样例输出 Copy

Case #1: 6
Case #2: 32

提示

第一个样例只有一个三角形,所以不用分割,答案是1*2*3=6。
第二个三角形,最优分割方案是分割为1 2 4和2 3 4两个三角形,答案是1*2*4+2*3*4=32

1<=t<=100
3<=n<=100
1<=a[i]<=100
 
一开始忘了输出格式,莫名wa了两发,剁手
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int n;
ll a[1000];
ll dp[1000][1000];
int ca=1;
void solve() {
    memset(a,0,sizeof 0);
    memset(dp,0,sizeof(dp));
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%lld",&a[i]);
    for(int i=n; i>=1; i--) {
        for(int j=i+1; j<=n; j++) {
            if(j-i==1)
                dp[i][j]=0;
            else if(j-i==2)
                dp[i][j]=a[i]*a[i+1]*a[i+2];
            else
                for(int k=i+1; k<=j-1; k++) {
                    dp[i][j]=max(dp[i][j],(dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]));
                }
        }
    }
    printf("Case #%d: ",ca++);
    printf("%lld\n",dp[1][n]);
}
int main() {
    int t;
    cin>>t;
    while(t--)
        solve();
    return 0;
}

问题 B: 奎奎发红包

题目描述

情人节又到了,又到了一年一度发红包的时间。经大家研究决定,今年让奎奎自愿发红包。
俱乐部有n个人(0<n<100000),每个人都有一个单身值v[i]与亲密度t[i](0≤v[i]≤10000,0≤t[i]≤10000),单身值越大的人,在情人节的时候就越羡慕奎奎,奎奎就需要给他更大的红包来安慰他。 由于一个寒假没有见到奎奎,领红包的时候大家都想跟奎奎py,花费时间t[i],先py后给红包噢。
大家都厌倦了等待,如果一个人等了时间t,那么奎奎发给他的红包大小就是v[i]·t。
但是奎奎还要和女朋友去快乐,想要花最少的钱来满足大家。
请你帮他计算最少需要发多少钱的红包。

输入

第一行一个整数n。接下来n行,每行两个数v[i]和t[i]。

输出

一个整数表示答案。

样例输入 Copy

4
1 4
2 3
3 2
4 1

样例输出 Copy

35

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std ;
const int N=100010;
typedef long long ll;
int f[N];
struct S {
    int v,t;
} st[N];
bool cmp(S a,S b) {
    return a.t*b.v<a.v*b.t;
}
int main() {
    int t=1;
    for(int c=1; c<=t; c++) {
        int n;
        cin>>n;
        for(int i=0; i<n; i++) {
            int s,e;
            cin>>s>>e;
            st[i]= {s,e};
        }
        sort(st,st+n,cmp);
        ll ans=0;
        ll sum=0;
        for(int i=0; i<n; i++) {
            ans+=st[i].t;
            sum+=st[i].v*ans;
        }
        cout<<sum<<endl;
    }
}

问题 C: 关于我转生变成史莱姆这档事

题目描述

关于我转生变成史莱姆这档事这部番剧中,上班族的三上悟因为某个事件而作为史莱姆在异世界转生了。在转生时得到了“大贤者”和“捕食者”这两个独特技能。虽然身为史莱姆,但也想和其他种族建立起友好关系。魔素是异世界里面魔物含有的魔力精华,捕食者这个技能就是吞噬魔素,捕食者的技能要求非常苛刻,如果你第一天吞噬了b魔素,那么你第二天可以吞噬第一天的2~9倍(必须是其中一个整数),也就是2b~9b,也就是说,史莱姆在第i天所吞噬的魔素一定是第i-1天的2~9倍,而且还必须是它的整数倍。
作为史莱姆手下的得力助手,哥布林们准备了大量的魔物供主人食用,现在史莱姆已经知道了这些魔物含有S魔素,现在请大贤者合理安排第一天要吞噬和接下来每天需要增加的魔素倍数,好让史莱姆能在最短的天数内恰好吞噬完魔素。由于大贤者要研究“哲学”,无暇顾及这些小事,现在只能请你帮忙,但是大贤者还建议,这些魔素至少要用两天来吞噬。
 

输入

一个正整数S,代表要吞噬的魔素总量。

输出

一个数,代表要吞噬的天数,如果无解输出-1。

样例输入 Copy

571

样例输出 Copy

5

提示

对于30%数据,有S<=100;
对于70%数据,有S<=107;
对于100%数据,有9<S<=8×108
 
玄学
#include<iostream>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f ;
int read()
{
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')             //判断正负
        flag=1;
    else if(ch>='0'&&ch<='9')           //得到完整的数
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
ll ans=INF;
ll calc(ll n)
{
    if(n<2)return INF;
    if(2<=n&&n<=9)return 1;
    ll res=INF;
    for(ll i=2;i<=9;++i)
        if(n%i==0)
        res=min(res,calc(n/i-1)+1);
    return res;
}
int main()
{
    ll n=read();
    for(ll i=1;i*i<=n;++i)
        if(n%i==0)
        {
            ans=min(ans,calc(n/i-1)+1);
            if(i!=1)
                ans=min(ans,calc(i-1)+1);
        }
    if(ans==INF)puts("-1");
    else std::cout<<ans;
    return 0;
}

问题 D: 大数

题目描述

小七是一个很可爱很努力的女孩子。她对大数的运算非常感兴趣,在学习了几天之后,终于精通了大数的加减乘除。但是自从她学会了 JAVA ,她觉得大数实在是太简单太无聊了,因为运用 JAVA 中 BigInteger 大整数类,可以轻松实现大数的加减乘除。某一天她突然发现,很多大数的题目的数据都有规律。这些数都是由比他小的某个数重复构成,比如说 121212 由 12重复构成 ,233233 ,由233重复构成,而1231231并不是由123重复构成。无聊的小七终于找到了乐子,她想要找到每个大数是由哪个比它小的数重复构成。算法刚入⻔的小七无法解决这个问题,于是她求助于你。
 

输入

一行 一个正整数n(n<=101000000)。

输出

一行
如果存在多种,输出最小的满足题意的数;
如果不存在,则输出-1.
 

样例输入 Copy

121212

样例输出 Copy

12

#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l; i <= r; ++ i)

using namespace std;

const int MaxN = 1e7 + 10;

int n;
char s1[MaxN];
int p[MaxN];

int main() {
    scanf("%s", s1 + 1);
    n = strlen(s1 + 1);
    if (n == 0) return 0;
    int j = 0;
    rep (i, 1, (n - 1)) {
        while (j > 0 && s1[j + 1] != s1[i + 1])
            j = p[j];
        if (s1[j + 1] == s1[i + 1])
            j ++;
        p[i + 1] = j;
    }
    if (n % (n - p[n]) != 0 || n == (n - p[n])) printf("-1");
    else rep (i, 1, n - p[n]) cout << s1[i];
    return 0;
}

问题 E: Ktree

题目描述

炼金术师灵岩在与巫师Slanely争夺馅饼的过程中处于劣势,于是灵岩召唤出了K树一起争夺馅饼。K树是一棵权值和为s但权值分配方式未定的树。Slanely偷偷施展法术,使K树的直径尽可能小。现在灵岩想知道召唤出的K树直径为多少。

输入

第一行给出两个整数n和s ,n,s<= 100000, n为节点数, s为树的总长度。
接下来,每行两个整数u,v,表示节点u和v之间有一条边相连。
 

输出

输出L,保留两位小数。

样例输入 Copy

6 4
1 2
1 3
1 4
4 5
4 6

样例输出 Copy

2.00

猜你喜欢

转载自www.cnblogs.com/QingyuYYYYY/p/12446909.html
今日推荐