Codeforces Round #750 (Div. 2)(A题~D题)

A. Luntik and Concerts 

题意:

我们有三首歌,一分钟的歌曲数量为a,两分钟的歌曲数量为b,三分钟的歌曲数量为c,我们要举行两场演唱会,现在我们把这三首歌分配给这两场演唱会,求这两场音乐会持续时间之间的最小分钟差。

思路:

a=1,b=2,c=3 我们将a,b,c都减去b(-1,0,1),我们求的是音乐会的时间差,那它们的运算还是不受影响的,我们设两场演唱会为x=0,y=0,将a安排到x,那么x=-1,y=0,这时x和y的差值为1,也就是相当于x=0,y=1,另外x=0,y=0,将c安排到y,那么x=0,y=1,这时x和y的差值为1,也就是相当于x=-1,y=0,也就是说音乐会持续时间之差与a歌和c歌的数量有关,我们将a放到x音乐会的时间差相当于将a放到y,将c放到y音乐会的时间差相当于将c放到x,从而得出a,b,c的歌曲时间可以转化为(1,0,1),所以我们可以得出x与y的差为(a+c)%2。

AC代码:

c++:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b,c,ans;
        cin>>a>>b>>c;
        ans=(a+c)%2;
        cout<<ans<<endl;
    }
}

python:

t = int(input())
for i in range(t):
    a,b,c = map(int,input().split())#一行输入多个值
    ans = (a+c)%2
    print(ans)

#关于‘输入’的知识点小记
a,b,c = map(int,input().split(','))#间隔输入,默认为空格
print(a,b,c)

def fun1(x):
    return x*x
a,b,c = map(fun1,[1,2,3])
print(a,b,c)

def fun2(x):
    x = int(x)
    return x*x
a,b,c = map(fun2,input().split())#输入的数据会经过fun函数的转换
print(a,b,c)

print(type(input().split()))#输入的数据类型为列表list,列表里的值的数据类型默认为字符串str

while True:#多组输入
    try:
        a, b, c = map(int, input().split())
        print(a,b,c)
    except:#出现异常(输入结束)退出循环
        break

B - Luntik and Subsequences 

题意:

我们有一个长度为n的序列,它的序列和为sn,如果x可以通过删除几个(可能是零个或全部)元素从y中获得,则序列x是序列y的子序列,求满足子序列和si=sn-1的子序列的数量。

思路:

我们要满足si=sn-1那么子序列里一定是有且只有一个1,而0是不会影响si的大小的,所以满足si=sn-1的子序列数量只与0和1的数量有关,而1在每个子序列里只会有一个,0是没有限制的,但0组成的子序列数量由2的n次方个,所以满足si=sn-1的子序列的数量为num1*pow(2,num0)。

AC代码:

c++:

#include<bits/stdc++.h>
using namespace std;
int a[65];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,num1=0,num2=0;
        long long ans;
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            if(a[i]==1)
            {
                num1++;
            }
            if(a[i]==0)
            {
                num2++;
            }
        }
        if(num1>0)
        {
            if(num2==0)
            {
                ans=num1;
            }
            else if(num2==1)
            {
                ans=num1+num1*num2;
            }
            else
            {
                ans=num1+num1*(pow(2,num2)-1);
            }
        }
        else
        {
            ans=0;
        }
        cout<<ans<<endl;
    }
    return 0;
}

python:

from math import *
t=int(input())
for i in range(t):
    n=int(input())
    a=list(map(int,input().split()))
    num1=a.count(1)
    num0=a.count(0)
    ans=int(num1*pow(2,num0))
    print(ans)

C - Grandma Capa Knits a Scarf

题意:

给定一个由小写英文字母组成的字符串,我们可以选择其中一种字符,判断是否可以将其删除任意个数使字符串成为回文字符串,求使字符串成为回文字符串删除字符的最小数量。

思路:

我们每次操作只能选择一种字符进行删除,那么我们可以将26字母全部枚举一遍,通过双指针指向字符串首尾两端,判断是否可以不断删除当前选择的这一种字符使得字符串成为回文字符串,并记录删除字符个数,最后比较得到最小值。

AC代码:

c++:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,ans,num,l,r,flag1,flag2=0;
        string s;
        cin>>n;
        cin>>s;
        ans=n;
        for(char c='a';c<='z';c++)
        {
            l=0,r=s.size()-1;
            num=0;
            flag1=1;
            while(l<r)
            {
                if(s[l]!=s[r])
                {
                    if(s[l]==c)
                    {
                        num++;
                        l++;
                    }
                    else if(s[r]==c)
                    {
                        num++;
                        r--;
                    }
                    else
                    {
                        flag1=0;
                        break;
                    }
                }
                else if(s[l]==s[r])
                {
                    l++;
                    r--;
                }
            }
            if(flag1)
            {
                flag2=1;
                ans=min(ans,num);
            }
        }
        if(!flag2)
        {
            ans=-1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

python:

t = int(input())
for i in range(t):
    n = int(input())
    s = input()
    ans = n
    flag1 = False
    for j in range(ord('a'),ord('z')+1):
        c = chr(j)
        l = 0
        r = n-1
        num = 0
        flag2 = True
        while l < r:
            if s[l] != s[r]:
                if s[l] == c :
                    num += 1
                    l += 1
                elif s[r] == c:
                    num +=1
                    r -= 1
                else:
                    flag2 = False
                    break
            else:
                l += 1
                r -= 1
        if flag2:
            flag1 = True
            ans = min(ans,num)
    if not flag1:
        ans = -1
    print(ans)

D - Vupsen, Pupsen and 0

题意:

给定一个数组a,其中没有值为0的元素,求得一个数组b,使得数组a和数组b各项乘积之和为0(\sum_{i=1}^n{(a_i*b _i)}=0),并且数组b中不能有元素的值为0。 

思路:

我们可以知道x*(-y)+y*x=0,也就是a[i]*(-a[i+1])+a[i+1]*-a[i]=0,这样就可以推出b[i]=a[i+1],b[i+1]=a[i],

但这只适用于数组长度为偶数时,数组元素可以两两配对,

而当数组长度为奇数时就会多出一个数,因为数组a和数组b都不存在元素0,所以数组a和数组b各项乘积之和不会为0,

这时我们就要单独处理这种情况了,我们知道只是处理多出来的这一个元素是无法满足a[i]*b[i]=0的,所以我们需要引入其它的元素和多出来的这一个元素配对,使得这个多出来的这一个元素和引入的元素可以满足a[i]*b[i]+a[i+1]*b[i+1]+a[i+2]*b[i+2]=0,如果这时数组内剩下的元素个数为偶数个,那么问题就迎刃而解了,

我们要让数组内剩下的元素个数为偶数个,就要拿出偶数个元素来与多出来的这一个元素配对,也就是拿出2个元素了与多出来的这一个元素配对计算量是最少的,

这时我们就只需要根据x*(-y)+y*x=0来推导如何使得a[i]*b[i]+a[i+1]*b[i+1]+a[i+2]*b[i+2]=0就可以了,我们要知道三个数配对可能存在两个数或三个数相等的情况,这时我们就要将它们分别计算了,

当三个数有两个数或三个数相同时(x,x,y),我们可以由x*(-y)+y*x=0推导出
x*(-y)+x*(-y)+y*(x+x)=0,

当三个数都不相同时(x,y,z),我们可以由x*(-y)+y*x=0推导出x*(-z)+y*z+z*(x-y)=0,当然三个数都相同对这个公式也是适用的,

这样在数组长度为奇数时,我们将三个数单独拿出来配对后,数组剩余的元素个数一定为偶数,我们只要将这些数组剩余的元素按照a[i]*b[i]+a[i+1]*b[i+1]+a[i+2]*b[i+2]=0两两配对就可以了。

AC代码:

c++:

#include<bits/stdc++.h>
using namespace std;
int a[100005],b[100005];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        if(n%2==0)
        {
            for(int i=0;i<n;i+=2)
            {
                printf("%d %d ",a[i+1],-a[i]);
            }
            printf("\n");
        }
        else if(n%2==1)
        {
            if(a[0]==a[2])
            {
                printf("%d %d %d ",-a[1],a[0]+a[2],-a[1]);
            }
            else if(a[0]!=a[2])
            {
                printf("%d %d %d ",-a[1],a[0]-a[2],a[1]);
            }
            for(int i=3;i<n;i+=2)
            {
                printf("%d %d ",a[i+1],-a[i]);
            }
            printf("\n");
        }
    }
    return 0;
}

python:

t = int(input())
for i in range(t):
    n = int(input())
    a = list(map(int,input().split()))
    if n % 2 == 0:
        for j in range(0,n,2):
            print(a[j+1],-a[j],end = ' ')
        print()
    else:
        if a[0] == a[2]:
            print(-a[1],a[0]+a[2],-a[1],end = ' ')
        else:
            print(-a[1],a[0]-a[2],a[1],end = ' ')
        for j in range(3,n,2):
            print(a[j + 1], -a[j], end=' ')
        print()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值