5.17周赛总结

这次周赛还是打成了一坨翔orzzzzzz。就出了两题。一开始看了A题,然后结果发现好像不是特别好做,看到有出了B,去看了B然后想了个脑残贪心,发现过不了,这时好多人过了C然后赶紧去看,结果确实是一个水题,赶紧写了交1Y,回来搞B结果B搞了好久,发现不是贪心,应该是类似完全背包的东西。还好过了,4Y。。。结果发现D应该比A题容易点,去写了D,发现一直会超时,感觉不知道在哪里优化。。。。期间还看了一下A,还是没什么思路,感觉是贪心又不肯定。还是搞D,直到周赛结束。两题悲剧。。。

A:http://codeforces.com/problemset/problem/437/B

题目定义了一个lowbit 其实就是将这个数字转化成二进制数之后看从右往左第一个出现的1在哪,它加上他右边的所有0就是这个lowbit的二进制表示,然而很容易推出对于每个十进制数的lowbit就是这个数能整除二 n次,这个lowbit就是2^n。这样就知道了lowbit,然后题目给了一个sum和一个limit,就是表示在1~limit的范围中的所有中任意选几个的lowbit,是否能组合成一个sum。(当然每个只能用一次)

然后就是运用一个排序,从大到小,贪心,找出是否能凑成sum,这一步就是在周赛的时候没有想到了,为什么没有想到呢,我思考过是否能运用贪心来做,但是感觉lowbit都是2^n,然而这个不完全是有序的,中间可能穿插了很多1,这样直接遍历的话应该是不行的,感觉没有想到从大往小的取,为什么这样是可以的呢,因为在lowbit数组中,大的数肯定是出现的次数肯定是比较少的。那么我们就先取大的往下取,如果加上这个数超过和的话就抛弃他,这样一定能找出是否能凑成sum。

这也确实体现了贪心思想也总是跟排序在一起的,也是个经验教训,思考问题的时候可能要多尝试,努力往前进一步。想运用贪心的时候却感觉不可以的时候,思考一下是否需要排序解决。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define M 100000
struct node
{
    int num,lb;
}s[M];
int ans[M];
int cmp(node a,node b)
{
    return a.lb > b.lb;
}
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)==2)
    {
        for(int i = 1;i <= m;i++)
        {
            int temp = 0;
            int a = i;
            while(a%2==0) //求lowbit
            {
                temp++;
                a = a/2;
            }
            s[i].num = i;
            s[i].lb = pow(2,temp);
        }
        sort(s+1,s+m+1,cmp);
        int sum = 0;
        int ok = 0;
        int a = 0;
        for(int i = 1;i <= m;i++)
        {
            if(sum + s[i].lb>n) continue; //抛弃这个数
            else
            {
                sum += s[i].lb; //贪心
                ans[a++] = s[i].num;
            }
            if(sum == n)
            {
                ok = 1;
                break;
            }
        }
        if(!ok)
        {
            printf("-1\n");
            continue;
        }
        printf("%d\n%d",a,ans[0]);
        for(int i = 1;i < a;i++)
        {
            printf(" %d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

B:http://acm.timus.ru/problem.aspx?space=1&num=1073

题意:就是给一个数n,把这个数拆成几个平方数之和,求最少要几个。

一开始用了贪心不可以做出来,后来改成类似完全背包的做法了,因为可以直接求出来有几种平方数,然而这每一种都可以用无限次,那么就是完全背包咯。

不过这里求的是最少几个,修改一下状态转移方程。

c[i] 表示第i个平方数 值为i*i;

定义p[i]表示的是i能拆成几个最少几个平方数的和,转移方程:p[j] = min(p[j],p[j-c[i]]+1); 就只有两种状态转移过来,一种是要这个平方数,另一种是不要。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define M 60009
#define INF 0x3f3f3f3f
int c[M];
int p[M];
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        if(n<=0)
        {
            printf("0\n");
            continue;
        }
        for(int i = 0;i <= n;i++)
        {
            p[i] = INF;
        }
        p[0] = 0;
        for(int i = 1;i*i <= n;i++)
        {
            c[i] = i*i;
        }
        for(int i = 1;i*i <= n;i++)
        {
            for(int j = c[i];j <= n;j++)
            {
                p[j] = min(p[j],p[j-c[i]]+1);
            }
        }
        printf("%d\n",p[n]);
    }
    return 0;
}

C题很水就不说了。

D:http://codeforces.com/problemset/problem/75/C

就是给两个数,然后再给几个询问,对于每个询问,两个数字,求在这两个数字之间的最大的公约数。

求出这两个数的最大公约数,然后求出这个最大公约数的所有因数就是这两个数的所有公约数。都存入一个set中

比赛的时候想到这里都还是对的,但是我在对每个区间进行查找的时候,我直接从大到小遍历查这个数在不在set里orzzzzzz,结果肯定跪了。。

应该运用二分查找,这次才知道set里本身就有二分的成员函数。。

为什么没有想到用二分查找呢,感觉是对于题目的分析还不够深入,如果找出第一个大于high的值,往回找一个如果在low跟high之间的话,那么就有,否则就没有。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
#define M 100000
int f[M];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)==2)
    {
        if(n>m) swap(n,m);
        set<int> ss;
        ss.insert(1);
        int a = m,b = n;
        while (a % b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        //printf("%d\n",b);
        ss.insert(b);
        int temp = b;
        for(int i = 2;i*i <= temp;i++) //循环遍历到根号
        {
            if(temp%i==0) //运用匹配的方法就可以一次找出两个。
            {
                ss.insert(i);
                ss.insert(temp/i);
            }
        }
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int a,b;
            int ok = 0;
            scanf("%d %d",&a,&b);
            set<int>::iterator it;
            it = upper_bound(ss.begin(),ss.end(),b);//后来才了解到set本身就有成员函数 upper_bound lower_bound()括号里为要查询的数
            if(*(--it)>=a)
                printf("%d\n",*it);
            else printf("-1\n");;
        }
    }
    return 0;
}

E题:模拟题。。但是我还是回去搞了好久,一直有点小问题。。。醉。

一开始分析错了,以为整个矩阵的宽度就是最大的y,发现并不是的。如果上升的话记为加,下降记为减,把这些值依次加起来,找出最小的,还有最大的,这两个差值就是宽度。然后我找出了最大的那个所在序列的位置,也就是最高峰。然后往右开始画,再往左。

不过这样好麻烦orzzzz,看了别人的发现好容易orzzzz,因为和不可能超过1000,所以将y初始化为1000,如果是上升就--,下降就++,记录下最小的y和最大的y,并且顺便将上升记成一种,下降记成一种。从最小的遍历到最大的就可以遍历所有的行了。。(不过都要注意的是在转折处不要加减了)

代码:方法一

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1009
#define INF 0x3f3f3f3f
int s[M];
char map[M][M];
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        int max1 = -INF;
        int max2 = -INF;
        int a = 0;
        int st = 0;
        int sum = 0;
        int temp = 0;
        int low = 0;
        for(int i = 0;i < n;i++)
        {
            scanf("%d",&s[i]);
            max2 = max(max2,s[i]);
            sum += s[i];
            if(i%2==0)
                temp += s[i];
            else temp -= s[i];
            if(max1 < temp)
            {
                max1 = temp;
                a = i;
                st = sum;
            }
            low = min(temp,low);
        }
        memset(map,' ',sizeof(map));
        int kk = 0;
        temp = st;
        for(int i = a+1;i < n;i++)
        {
            if(i%2==0)
            {
                for(int j = 0;j < s[i];j++)
                {
                    if(j!=s[i]-1)
                    map[kk--][temp++] = '/';
                    else map[kk][temp++] = '/';
                }
            }
            else
            {
                for(int j = 0;j < s[i];j++)
                {
                    if(j!=s[i]-1)
                    map[kk++][temp++] = '\\';
                    else  map[kk][temp++] = '\\';
                }
            }
        }
        kk = 0;
        st--;
        for(int i = a;i >= 0;i--)
        {
            if(i%2==0)
            {
                for(int j = 0;j < s[i];j++)
                {
                    if(j!=s[i]-1)
                    map[kk++][st--] = '/';
                    else map[kk][st--] = '/';
                }
            }
            else
            {
                for(int j = 0;j < s[i];j++)
                {
                    if(j!=s[i]-1)
                    map[kk--][st--] = '\\';
                    else map[kk][st--] = '\\';
                }
            }
        }
        for(int i = 0;i < max1-low;i++)
        {
            for(int j = 0;j < sum;j++)
                putchar(map[i][j]);
            putchar('\n');
        }
    }
    return 0;
}
二:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 2009
#define INF 0x3f3f3f3f
int s[M];
int map[M][M];
int main()
{
    int n;
    //putchar('\\');
    while(scanf("%d",&n)==1)
    {
        int maxy = -INF;
        int miny = INF;
        int x = 0,y = 1000;
        memset(map,0,sizeof(map));
        for(int i = 0;i < n;i++)
        {
            scanf("%d",&s[i]);
            for(int j = 0;j < s[i];j++)
            {
                if(i%2==0)
                {
                    maxy = max(maxy,y);
                    miny = min(miny,y);
                    if(j!=s[i]-1)
                    map[y--][x++] = 1;
                    else map[y][x++] = 1;
                }
                else
                {
                    maxy = max(maxy,y);
                    miny = min(miny,y);
                    if(j!=s[i]-1)
                    map[y++][x++] = -1;
                    else map[y][x++] = -1;
                }
            }
        }
        for(int i = miny;i <= maxy;i++)
        {
            for(int j = 0;j < x;j++)
            {
                if(map[i][j]==0)
                    putchar(' ');
                else if(map[i][j]==1)
                    putchar('/');
                else putchar('\\');
            }
            putchar('\n');
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值