zoukankan      html  css  js  c++  java
  • BestCoder Round #71 (div.2)

    比赛链接:click here

    题解:

    KK's Steel

    问题描写叙述
    我们可爱的KK遇到了一道数学难题:对于一条长为Nleft( 1leq Nleq {10}^{18}
    ight)N(1N1018)米的钢管,最多能够锯成几根小钢管,使得锯成的钢管互不相等且均不能围成三角形。
    输入描写叙述
    第一行一个数Tleft( 1leq Tleq 10
    ight)T(1T10),表示数据组数。
    接着T行,每行一个整数Nleft( 1leq Nleq {10}^{18}
    ight)N(1N1018),表示钢管的长度。
    输出描写叙述
    对于每个数据输出一个整数,表示能够锯成的钢管数。
    输入例子
    1
    6
    输出例子
    3
    Hint
    1+2+3=6 1+2=3 他们都不同样且他们不能构成三角形。
    题解:

    已经忘记是哪一年的慈溪中学提前招生数学试卷里的题目了。

    事实上我们不去考虑N,我们仅仅考虑最优分割策略:

    首先肯定是尽量的小即1、2

    既要不相等,又不能构成三角形。即每次为当前数列中最大的两项的和

    那么,构成的数列为1,2,3,5,8,......

    这样我们仅仅要求最接近且小于等于N的Fibonacci数的项数就可以。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef  unsigned long long LLU;
    LLU a[1000]={1,1};
    int main()
    {
        for(int i=2; i<100; ++i) a[i]=a[i-1]+a[i-2];
        for(int i=2; i<100; ++i) a[i]+=a[i-1];
        int t;scanf("%d",&t);
        while(t--)
        {
            LLU n; scanf("%I64u",&n);
            for(LLU i=0; i<n; ++i)
            {
                if(a[i]>n)
                {
                    printf("%I64u
    ",i-1);
                    break;
                }
            }
        }
        return 0;
    }
    


    KK's Point

    问题描写叙述
    我们可爱的KK遇到了一道数学难题:他在一个圆上点下了互不重合的Nleft(2leq Nleq {10}^{5} 
    ight)N(2N105)个点,如今他要将这NN个点两两相连(圆内没有三条线交于一个点的情况),KK想知道图形中一共同拥有多少个交点(包含边界上的点)。
    输入描写叙述
    第一行一个数Tleft( 1leq Tleq 10
    ight)T(1T10),表示数据组数。
    接着T行,每行一个整数Nleft(2leq Nleq {10}^{5} 
    ight)N(2N105)。表示圆上的点数。
    输出描写叙述
    对于每个数据输出一个整数,表示交点数。

    输入例子
    2
    3
    4
    输出例子
    3
    5

    题解:

    我们先撇开边界上的点无论。那么全部的点都是有两条线所构成的,手算得出N=4的时候,能形成一个点。那么。我们仅仅要知道N个点能够构成几个四边形就可以即求C(n,4),最后我们再把边界上的N个点加上, 最后的结果是C(n,4)+n;

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef  unsigned long long LLU;
    int main()
    {
        int t;scanf("%d",&t);
        while(t--)
        {
            LLU n; scanf("%I64u",&n);
            LLU ret=0;
            if(n>=4) ret=ret+n*(n-1)/2*(n-2)/3*(n-3)/4;
            ret+=n;
            printf("%I64u
    ",ret);
        }
        return 0;
    }


    KK's Chemical

    问题描写叙述
    我们可爱的KK有一道困难的化学题目:实验室有Nleft(1leq Nleq 100 
    ight)N(1N100)瓶化学药品。编号为00N-1N1,如今KK知道第i瓶当且仅当和第c[i]c[i]瓶放在一起时会发生爆炸。

    KK得到任务要整理实验室,他须要将他们装进k个不同的盒子里。显然。为了KK的生命安全,你不能把两瓶会造成爆炸的药品放进同一个箱子。如今KK想知道有多少种不同的方案。因为答案可能会很很的大。全部将最后答案取{10}^{9}+7109+7的模就可以。保证c[i] eq ic[i]i

    输入描写叙述
    第一行一个数Tleft( 1leq Tleq 200
    ight)T(1T200),表示数据组数。
    每组数据两行,第一行两个整数Nleft(1leq Nleq 100 
    ight)N(1N100)Kleft(1leq Kleq 1000 
    ight)K(1K1000),表示化学药品的个数和须要放入的盒子数。
    接下来第二行NN个整数c[i]left( 0leq c[i]leq N-1
    ight)c[i](0c[i]N1)
    输出描写叙述
    对于每个数据输出一个整数,表示方案数对{10}^{9}+7109+7取模后的结果。
    输入例子
    3
    3 3
    1 2 0
    4 3
    1 2 0 0
    3 2
    1 2 0
    输出例子
    6
    12
    0
    题解:

    依据药品之间的相互关系。我们能够构建一张图。我们对相互会发生反应的药品连边

    这个图的特征,是一个环加上一些“树”(可能有多个联通块)

    一个环(1,2,3,4,5……。n)m染色的方案数:递推,设第一个点颜色为1

    f[I,1]表示i点颜色为1的种数,f[I,0]为颜色不为1时(不考虑n与1颜色不同)

    则F[I,0]=f[i-1,0]*(m-2)+f[i-1,1]*(m-1),F[I,1]=f[i-1,0]

    那么方案数为f[n,0]*m

    一个根节点颜色固定且有k个孩子的树的m染色的方案数={(m-1)}^{k}(m1)k,由于每一个点的颜色仅仅要与他的父亲颜色不同,即m-1种

    由于乘法原理。一个联通块的方案数=环方案数*以环上每一个点为根的树的积。多个联通块。再连乘就可以。

    KK's Number

    问题描写叙述
    我们可爱的KK有一个有趣的数学游戏:这个游戏须要两个人,有Nleft(1leq Nleq 5*{10}^{4} 
    ight)N(1N5104)个数。每次KK都会先拿数。每次能够拿随意多个数,直到NN个数被拿完。

    每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大。在这种情况下,终于KK的得分减去对手的得分会是多少?

    输入描写叙述
    第一行一个数Tleft( 1leq Tleq 10
    ight)T(1T10),表示数据组数。
    对于每组数据包括两行,第一行一个整数Nleft(1leq Nleq 5*{10}^{4} 
    ight)N(1N5104),表示个数,第二行NN个正整数(不超过{10}^{9}109)。
    输出描写叙述
    对于每个数据输出一个整数,表示终于KK的得分减去对手的得分。

    输入例子
    1
    3
    1 3 1
    输出例子
    2
    Hint
    首先KK取走3,然后对手取走两个1,那么终于分差为2。

    题解:

    显然。每一个人的策略就是都会拿剩下的数中最大的某几个数

    假如我们用f[i]表示当剩下i个数的时候先手得分-后手得分的最小值

    那么得到f[i]=maxleft(a[j+1]-f[j] ight)(1<jleq i)f[i]=max(a[j+1]f[j])(1<ji)

    可是这样做。是要超时的

    我们最好还是简单转换一下 f[i]=_max; _max=max(_max,a[i+1]-f[i]);

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef  unsigned long long LLU;
    const int maxn = 1e5+10;
    int a[maxn],b[maxn];
    int main()
    {
        int t;t=read();
        while(t--)
        {
            int n,maxx=0; n=read();
            for (int i=1; i<=n; i++)  a[i]=read();
            sort(a+1,a+n+1);
            for (int i=1; i<=n; i++)  maxx=max(maxx,a[i]-b[i-1]),b[i]=maxx;
            printf("%d
    ",b[n]);
        }
        return 0;
    }



  • 相关阅读:
    HWOJ之纠结的优化
    java中的对象数组
    短路特性的运用
    归并排序
    两个有序数列的合并
    java中的注释规范
    堆排序
    堆的建立
    希尔排序
    直接插入排序
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7088752.html
Copyright © 2011-2022 走看看