2020.5.20--习题一 题解

A - Phoenix and Balance

题解:有n个分别为2^1, 2^2 , 2^3…2^n的数,n为偶数,将这n个数平均分为两组,求这两组差的绝对值最小值

方法:将数2^n分给一组,第n/2到第n-1的数分给第二组,剩下的分到一组,求两组差的绝对值

2到2^n这n个数中,2^n大于剩下n-1个数的和。因此,把2^n分给一组后,一组的数就已经肯定大于二组了,所以把剩下数大的都给二组,小的都给一组

#include<bits/stdc++.h>
using namespace std;
int f(int n){
    int i,sum=1;
    for(i=1;i<=n;i++)
    {
        sum*=2;
    }
    return sum;
}
int main()
{
    int t,n,sum,num;
    cin>>t;
    while(t--)
    {
        sum=0;
        num=0;
        cin>>n;
        for(int i=n/2;i<=n-1;i++)
        {
           sum+=f(i);
        }
        for(int j=1;j<n/2;j++)
        {
            num+=f(j);
        }
        num+=f(n);
        cout<<abs(num-sum)<<endl;
    }
}

B - Phoenix and Beauty

 题解:给出t个测试用例,每例第一行输入n,k,第二行输入长度为n的数组,在数组中插入一些数,插入的数介于1和n之间,使所有长度为k的子阵具有相同的和

如果输入的数组中不同的数的个数大于k,那么就输出-1;

其余情况下:因为不需要使插入后的数组长度最小化,所以可以使最终长度为n*k,先找出数组中不同值的数并存储起来,然后输出这些不同的数,如果长度不足k则用1或其他任意介于1和n之间的数来补上,最后再将该长度为k的子序列循环n次

#include<bits/stdc++.h>
using namespace std;
//第一行应包含美丽阵列的长度m(n≤m≤104)。你不需要最小化m。
int main()
{
   int t;
   cin>>t;
   while(t--)
   {
       int n,k;
       int sum=0,ct=0;
       cin>>n>>k;
       int s[n+5],b[n+5]={0},d[n+5],max=-1;
       for(int i=0;i<n;i++)
       {
           cin>>s[i];
       }
       for(int i=0;i<n;i++)
       {
           if(b[s[i]]==0)//找不同值的数
           {
               b[s[i]]=1;
              
               d[ct++]=s[i];//存储不同值的数并记录不同值的个数
            }
       }
      // cout<<ct<<endl;
       if(ct>k)cout<<"-1"<<endl;
       else
       {
           cout<<n*k<<endl;

           for(int i=0;i<n;i++)
           {
               for(int j=0;j<ct;j++)
               {
                   cout<<d[j]<<" ";
               }
               for(int j=ct;j<k;j++)cout<<"1 ";
           }
           cout<<endl;
       }
   }
}

C - Road To Zero

题解:输入两个数,有两种操作,1--消耗a两数中任意一个数减少或增加1,2--消耗b使两数均减少或增加1,最终使两数均为0,不一定同时为0,求最少花费是多少

 先操作1计算其中大数到较小数时的花费abs(x-y)*a,再加上操作2时两数同时减或加1的花费;与两数分别进行a操作的总花费比较,求出较小那个费用,即为答案

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long t,x,y,a,b,ct;
    cin>>t;
    while(t--)
    {
        ct=0;
        cin>>x>>y;
        cin>>a>>b;
        long long sum=0;
        ct=min(x,y)*b+abs(x-y)*a;
        sum=(x+y)*a;
        cout<<min(ct,sum)<<endl;
    }
}

 

D - Binary Period

题解:输入由0和1组成的子字符串t,求使循环周期最短的字符串s(t是s的子字符串,s的长度不超过2*|t|,且由0和1组成),如果可以通过删除0个或多个元素而不改变其他元素的顺序得到t,那么t也是s的子序列

根据样例和题目可以看出如果t只有0或1,则输出原输入即可,若t中既有1也有0,则输出|t|个“10“组合

#include<bits/stdc++.h>
#include<string>
using namespace std;
int main()
{
   int t;
   cin>>t;
   while(t--)
   {
       char s[110];
       int i,j,k=0,p=0;
       scanf("%s",&s);
       int m;
        m=strlen(s);
         for(i=0;i<m;i++)
         {
             if(s[i]=='0')
             {
                 k=1;
             }
             else if(s[i]=='1')p=1;
         }
         if((k==1&&p!=1)||(k!=1&&p==1))cout<<s<<endl;
         else if(k==1&&p==1)
         {
             for(i=0;i<m;i++)
             {
                 printf("10");
             }
             cout<<endl;
         }
   }


}

E - Nastya and Rice

题解:有n颗颗粒,每颗重量在a-b和a+b之间,总重量在c-d和c+d之间,给出t个测试用例,对于满足条件的输出“Yes",否则输出“No"

合格的标准是:

c-d<=n*(a-b)<=x<=n*(a+b)<=c+d

所以当n*(a-b)>c+d||n*(a+b)<c-d时输出No

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,a,b,c,d;
        int k=0;
        cin>>n>>a>>b>>c>>d;
            if(n*(a-b)>(c+d)||n*(a+b)<(c-d))cout<<"No"<<endl;
            else cout<<"Yes"<<endl;
    }
}

F - Nastya and Door

 题解:给出n个数,找出长度为k的一段数,使其中的山峰数最多,并求出这k段数的最左端的数

样例一:1 2 4 1 2 4 1 2

      b[i]:  0 0 0 1 1 1 2 2

#include<bits/stdc++.h>
using namespace std;
//int s[10000],b[10000]=0;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,k,p=0,m=0,x=1;
        cin>>n>>k;
        int s[n+5],b[n+5];
        for(int i=0;i<n;i++)
        {
            cin>>s[i];
            if(i>=2&&s[i-1]>s[i-2]&&s[i-1]>s[i])
            {
                p++;//记下山峰的数量
            }
            b[i]=p;//记录山峰的下标
            //cout<<b[i]<<endl;
        }

      样例一:1 2 4 1 2 4 1 2

      b[i]:  0 0 0 1 1 1 2 2

for(int i=0;i<n-k+1;i++)
         {
             if(m<b[i+k-1]-b[i+1])//k段中山峰的数量 1≤Lnk+1
             {
                  x=i+1;
             }
             m=max(m,b[i+k-1]-b[i+1]) ;
         }
          cout<<m+1<<" "<<x<<endl;
    }
}

 

猜你喜欢

转载自www.cnblogs.com/mxw000120/p/12923995.html