• CDOJ 第七届ACM趣味程序设计竞赛第三场(正式赛) 题解


    宝贵资源

    题目连接:

    http://acm.uestc.edu.cn/#/problem/show/1265

    题意

    平面上给n个点(n<=1000),要求找一个面积最小的正方形,将所有的点都囊括进去。

    要求正方形的边必须平行于坐标轴。

    题解:

    对于这道题,我们可以首先找一个满足题意的,并且面积是最小的矩形。

    假设矩形的长为L,宽为W,那么很显然:

    L = (MaxX - MinX)
    W = (MaxY - MinY) 
    

    MaxX,MaxY 指题目中输入的最大横、纵坐标的值,MinX,MinY 指题目中输入的最小横,纵坐标的值。

    因为我们需要得到正方形,那么正方形的边长

    L 取 max(L,W)即可。
    

    这道题就结束了~

    代码如下:

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    
    unsigned long long x1=99999999999LL,x2=0,y1=99999999999LL,y2=0;
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            unsigned long long X ,Y;
            cin>>X>>Y;
            x1 = min(x1,X);
            x2 = max(x2,X);
            y1 = min(y1,Y);
            y2 = max(y2,Y);
        }
        unsigned  long long l = max(x2-x1,y2-y1);
        cout<<l*l<<endl;
    }
    

    The Desire of Asuna

    题目连接:

    http://acm.uestc.edu.cn/#/problem/show/1263

    题意

    给你n条链,每条链的长度为a[i]

    每次操作你可以选择一条链,使得这条链的长度减1,然后使得任意两条链连接在一起,连接之后的长度要加1。

    询问最少操作次数。

    题解:

    贪心。

    我们选择长度减小的链,一定是可选的,并且长度最小的链。

    我们选择合并的链,一定是当前长度最大的两条链。

    为什么?

    假设所有的链的长度都是无限长,这道题的答案毫无疑问就是 n-1

    但是长度并不是无限长的,所以我们可以通过 使得链长度-1 的这个操作,去除一些链,使得答案比 n-1 小

    很容易可以看出,我们之前的贪心策略,可以使得尽量多的链在 长度-1 这个阶段就被消去了。

    所以这道题就结束了。

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    int a[2005];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+1+n);
        int l = 1,r = n;
        int ans = 0;
        while(l<r)
        {
            a[l]--;
            r--;
            ans++;
            a[r]+=a[r+1]+1;//这句话可有可无
            if(a[l]==0)l++;
        }
        printf("%d
    ",ans);
    }
    

    人民币的构造

    题目连接:

    http://acm.uestc.edu.cn/#/problem/show/1264

    题意

    给你n,要求你找到最少的数,并且这些数最多使用一次。

    使得通过加减可以构成1-n中的所有数。

    问你最少多少个数。

    题解:

    数学题

    假设 现在 [1,K] 范围内的数,你都能得到

    那么你加入一个数之后,能够构造出的最大的数是多少?

    答案是3K+1

    为什么?

    假设你加入的数是 A , 那么至少 K+1到A-1 范围内数,你必须通过 A - X 来得到。

    [A-K,A-1],这玩意是造出来的,为了使得A最大,考虑A-K=K+1,因为要连续,所以A= 2K+1

    所以 最多能构造出 A + K = 3K + 1

    所以就可以得到结论,1张钱最多构造1元,2张钱构造4元,3张13元,4张40元......

    所以这道题就结束了。

    代码

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    int main()
    {
        int n;
        scanf("%d",&n);
        int ans = 1;
        int l = 1;
        int sum = 1;
        while(sum<n)
        {
            l = sum*2+1;
            sum += l;
            ans++;
    
        }
        printf("%d
    ",ans);
    }
    

    奇怪的四元数

    题目连接:

    http://acm.uestc.edu.cn/#/problem/show/1266

    题意

    四元数是由实数加上三个元素i,j,k组成,而且它们有如下的关系:

    i^2=j^2=k^2=−1

    i×j=−j×i=k

    j×k=−k×j=i

    k×i=−i×k=j

    显然,四元数不满足交换律。现在给你一个长度为N的四元数乘法表达式(只包含i,j,k),为了使它的结果等于1,你可以选取表达式中的任意两个数进行交换,但交换次数不能大于M次。

    若可能使结果为1,输出交换的最少步数。

    否则,输出−1。

    题解:

    数学题

    这道题的结论如下:

    1.如果这个串最后答案是i,j,k的话,直接输出-1

    2.如果这个串最后答案是1的话,输出0

    3.如果这个串最后答案是-1的话,非特殊情况输出1,否则输出-1

    特殊情况如下:

    1.m=0

    2.这个串只含有i,j,k.(交换和不交换都一样.

    关于结论的证明

    第一个结论证明:

    显然成立,换位只改变符号。

    第二个结论也显然成立。

    第三个结论:

    首先意识到,虽然不满足交换律,但是满足结合律。

    即 ijk = i(jk)

    那么我们只要随便交换两个相邻的不同的字符就好,就可以使得答案乘上-1了

    代码

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    char s[1005];
    int flag[4][4]={
        {0,1,2,3},
        {1,0,3,2},
        {2,3,0,1},
        {3,2,1,0}
    };
    
    int idx(char c)
    {
        if(c=='i')return 1;
        if(c=='j')return 2;
        if(c=='k')return 3;
        return 0;
    }
    int main()
    {
        int n,m;
        scanf("%d%d%s",&n,&m,s);
        int sig=1;
        int now = 0;
        int Test =  0;
        for(int i=0;i<n;i++)
        {
            if(i>0&&s[i]!=s[i-1])
                Test=1;
            int k = idx(s[i]);
            if(now == k)
            {
                sig = sig * (-1);
                now = 0;
            }
            else
            {
                if(now==1&&k==3)
                    sig = sig * (-1);
    
                if(now==2&&k==1)
                    sig = sig * (-1);
    
                if(now==3&&k==2)
                    sig = sig * (-1);
    
                now = flag[now][k];
            }
        }
    
        if(now)return puts("-1");
        if(sig==-1&&Test==0)return puts("-1");
        if(sig==1)return puts("0");
        else if(sig==-1&&m>0)return puts("1");
        return puts("-1");
    }
    

    Memory

    题目连接:

    http://acm.uestc.edu.cn/#/problem/show/1262

    题意

    有n瓶药,其中有两瓶药的药丸比其他的都轻0.1g

    你需要构造出一种方案,使得无论哪两种药瓶里的药有问题都可以通过一次测量得到答案。

    要求方案的字典序最小。

    题解:

    暴力

    1.首先 fib 是错的。

    2.如果n=2,注意输出1,1

    3.数据范围只有52.

    假设你现在已经构造出了数据为n的方案了,那么我们现在加一个数进去,这个数应该是多少呢?

    直接暴力。

    从小到大暴力,看哪个数与之前n个数的和都没有出现过。

    然后这道题就结束了。

    代码

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    int a[100000];
    int ans[60];
    int check(int x,int tot)
    {
        for(int i=1;i<tot;i++)
            if(a[ans[i]+x]==1)
                return 0;
        return 1;
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        if(n==2)return puts("1 1");
        a[3]=1;
        ans[1]=1,ans[2]=2;
        for(int i=3;i<=n;i++)
        {
            for(int j=1;;j++)
            {
                if(check(j,i))
                {
                    ans[i]=j;
                    break;
                }
            }
            for(int j=1;j<i;j++)
                a[ans[i]+ans[j]]=1;
        }
        for(int i=1;i<=n;i++)
            printf("%d ",ans[i]);
        printf("
    ");
    }
  • 相关阅读:
    关于服务器并发量的简单计算
    重温Android和Fragment生命周期
    JVM类加载机制
    设计六大原则总结
    Android Navigation使用
    Android BrocastReceiver解析
    Android LiveData使用
    Android Service解析
    Activity的生命周期和启动模式
    Java四种引用
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5041126.html
Copyright © 2020-2023  润新知