AtCoder Beginner Contest 136 题解

A - Transfer:
题意:
两个杯子,第一个杯子可以装A升水,此刻已经装了B升水,第二个杯子此刻装了C升水。将第二个杯子里的水尽可能的导入第一个杯子直至第一个杯子装满水或者第二个杯子里的水倒完。
问最后第二个杯子剩余多少水?
题解:
比较(A-B)和C的大小,前者大,则第二个杯子的水倒完,后者大,则第一个杯子被装满,第二个杯子的水还剩余C-(A-B)升水。
AC代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    int a,b,c;
    cin>>a>>b>>c;
    int d=a-b;
    c-=d;
    cout<<max(0,c);
	return 0;
}

B - Uneven Numbers
题意:
给出一个n,统计小于等于n的所有数中位数是奇数的个数。
题解:
方法一:
由于n不大,所以直接遍历所有小于等于n的数,奇数则答案加一。
AC代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    int n;
    cin>>n;
    int ans=0;
    bool f=true;
    for(int i=1;i<=n;i++)
    {
        if(i==10||i==100||i==1000||i==10000||i==100000)
            f=!f;
        if(f)
            ans++;
    }
    cout<<ans;
	return 0;
}

方法二:
根据n去计算有多少个奇数位。
AC代码:

#include <bits/stdc++.h>
using namespace std;
int qpow(int a,int b)//计算a的b次方
{
    int ret=1;
    while(b!=0)
    {
        if(b&1)
            ret*=a;
        a*=a;
        b>>=1;
    }
    return ret;
}
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    int n;
    cin>>n;
    int x=n,len=0,ans=0;
    while(x!=0)//计算长度
    {
        x/=10;
        len++;
    }
    for(int i=1;i<len;i+=2)//统计每一个奇数长度的数字的个数
    {
        ans+=9*qpow(10,i-1);
    }
    if(len&1)//统计最大奇数长度的数字的个数
        ans+=n-qpow(10,len-1)+1;
    cout<<ans;
	return 0;
}

C - Build Stairs
题意:
有n个高度分别为hi的东西,现在对于每一个东西,你可以选择将其高度减一或者不变,问有没有可能使整个高度序列从左到右为非递减序列。
题解:
从左到右记录当前位置的最低高度,如果下一个东西的高度比他低则不肯能,反之,更新最低高度为(下一个东西的高度减一)和(当前最低高度)的最大值。
AC代码:

#include <bits/stdc++.h>
using namespace std;
int h[maxn];
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    int n;
    cin>>n>>h[1];
    int low=h[1]-1;
    bool f=true;
    for(int i=2;i<=n;i++)
    {
        cin>>h[i];
        if(h[i]>low)
        {
            low=h[i]-1;
        }
        else if(h[i]==low)
        {
            low=h[i];
        }
        else
        {
            f=false;
        }

    }
    if(f)
        cout<<"Yes";
    else
        cout << "No";
	return 0;
}

D - Gathering Children
题意:
有一个只包含‘R’和‘L’的字符串,且保证最左端一定使‘R’,最右端一定使‘L’。
现在字符串上的每一个位置上都对应着一个小孩儿,每个时刻每一个小孩会根据他所待位置的字母向左或者向右移动一格。问10的100次方时刻后每一个位置上小孩儿的数量。
题解:
因为最左端和最右端分别为R和L,所以不可能走出字符串。
那么我们可以将字符串按照连续相邻的R和L分隔开,将连续的R和L当作一个整体,每一个R整体必然与之对应一个L整体,每一个L整体也对应着一个R整体。
并且R与L在10的100次方时刻后必然只在两个整体相接触的位置上有小孩儿。
每两个RL整体自成一个无限循换交换。
那么现在我们来分析一个RL整体。
记R的个数为r,L的个数为l。
(1)r=l
最终在接触的地方各有r个小孩儿。
(2)r<l
先在r时刻,形成接触的位置各有r个小孩儿,但在右边的l-r个位置上还各自停留着一个小孩,之后每一个时刻会接触的地方进入一个小孩,那么将在 l 时刻达到平衡。由于10的100次方为偶数,所以如果l为奇数,那么下一时刻的平衡就是最终的平衡状态。如果l为偶数,那么此时的状态就是最终的平衡状态。
(3)r>l
分析同上。
AC代码:

#include <bits/stdc++.h>
using namespace std;
int num[maxn];//记录接触位置R或者L的个数
bool vis[maxn];//标记接触位置
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    string s;
    cin>>s;
    memset(vis,false,sizeof(vis));
    int n=s.length();
    int now=1,cnt=1;
    int lftpos=0;
    for(int i=1;i<n;i++)//统计接触位置R或者L的个数
    {
        if(now==1)
        {
            if(s[i]=='R')
            {
                cnt++;
            }
            else
            {
                vis[i-1]=true;
                num[i-1]=cnt;
                now=2;
                lftpos=i;
                cnt=1;
                vis[i]=true;
            }
        }
        else if(now==2)
        {
            if(s[i]=='L')
            {
                cnt++;
            }
            else
            {
                num[lftpos]=cnt;
                cnt=1;
                now=1;
            }
        }
    }
    num[lftpos]=cnt;
    for(int i=0;i<n;i++)
    {
        if(!vis[i])
            cout<<"0 ";
        else
        {
            int l=num[i],r=num[i+1];
            int sum=l+r;
            if(l==r)
            {
                cout<<l<<" "<<r<<" ";
            }
            else if(l<r)
            {
                int mi=(l+1)%2;达到两边初始平衡所需时间
                int d=(r-l)&1;//将所有孩子纳入平衡所需时间
                int z=(mi+d)%2;//总数的奇偶性
                l=(sum)/2;
                r=(sum+1)/2;
                if(z&1)
                {
                    cout<<r<<" "<<l<<" ";
                }
                else
                {
                    cout<<l<<" "<<r<<" ";
                }
            }
            else
            {
                int mi=(r+1)%2;
                int d=(l-r)&1;
                int z=(mi+d)%2;
                l=(sum+1)/2;
                r=(sum)/2;
                if(z&1)
                {
                    cout<<r<<" "<<l<<" ";
                }
                else
                {
                    cout<<l<<" "<<r<<" ";
                }
            }
            i++;
        }
    }
	return 0;
}

E - Max GCD
题意:
有一个长度为n的序列,现在你可以进行最多k次操作:
每一次操作是将Ai减一并且Aj加一,(i!=j)。
求最多进行k次操作后,这个序列所有数字的最小公因数。
因数的定义:x是y 的因数,即存在一个整数z使得y=x*z成立。
题解:
既然是所有数字的因数,那么必然是所有数和的因数。且无论进行几次操作,和都不会改变。
所以可以枚举序列和的因子,依次判断能否在k次操作后,使该因子为所有数的因子。
判断过程:
将a数组每一个%因子后存入b数组。从小到大排序,较大的加,较小的减,看能否在k次操作内,使b数组全为0。
AC代码:

#include <bits/stdc++.h>
using namespace std;

#define LL long long

int a[maxn],b[maxn];
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
   	cout.tie(0);
    int n,k;
    cin>>n>>k;
    int sum=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
    int mx=sqrt(sum)+1;
    int ans=1;
    for(int i=1;i<=mx;i++)
    {
        if(sum%i==0)
        {
            bool ok=true;
            for(int j=0;j<n;j++)
            {
                b[j]=a[j]%i;
            }
            sort(b,b+n);
            int l=0,r=n-1;
            while(b[l]==0)
            {
                l++;
            }
            int need=0,lft=0,hav=0;
            while(l<r)
            {
                if(lft==0) lft=b[l]-0;
                if(hav==0) hav=i-b[r];
                if(lft==hav)
                {
                    need+=hav;
                    hav=lft=0;
                    l++,r--;
                }
                else if(lft>hav)
                {
                    need+=hav;
                    lft-=hav;
                    hav=0;
                    r--;
                }
                else
                {
                    need+=lft;
                    hav-=lft;
                    lft=0;
                    l++;
                }
                if(need>k)
                {
                    ok=false;
                }
            }
            if(l==r)ok=false;
            if(ok)
            {
                ans=max(i,ans);
            }

            int x=sum/i;
            ok=true;
            for(int j=0;j<n;j++)
            {
                b[j]=a[j]%x;
            }
            sort(b,b+n);
            l=0,r=n-1;
            while(b[l]==0)
            {
                l++;
            }
            need=0,lft=0,hav=0;
            while(l<r)
            {
                if(lft==0) lft=b[l];
                if(hav==0) hav=x-b[r];
                if(lft==hav)
                {
                    need+=hav;
                    hav=lft=0;
                    l++,r--;
                }
                else if(lft>hav)
                {
                    need+=hav;
                    lft-=hav;
                    hav=0;
                    r--;
                }
                else
                {
                    need+=lft;
                    hav-=lft;
                    lft=0;
                    l++;
                }
                if(need>k)
                {
                    ok=false;
                    break;
                }
            }
            if(l==r)ok=false;
            if(ok)
            {
                ans=max(ans,x);
            }
        }
    }
    cout<<ans;
	return 0;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/98484570
今日推荐