buct12月月赛总结

好久没写博客了。。。。

这次是大学后第一次博客,用来总结12月月赛。8道A了6道。AB等补充。

题C:机器人

题目描述
有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去。机器人有一个初始能量,每个格子对应一个整数A[i],表示这个格子的能量值。如果A[i] > 0,机器人走到这个格子能够获取A[i]个能量,如果A[i] < 0,走到这个格子需要消耗相应的能量,如果机器人的能量 < 0,就无法继续前进了。问机器人最少需要有多少初始能量,才能完成整个旅程。

例如:n = 5。{1,-2,-1,3,4} 最少需要2个初始能量,才能从1号走到5号格子。途中的能量变化如下3 1 0 3 7。

1e9>=n>=1

-1e5<=A[i]<=1e5

输入
给定一个n,接下来n行,每行一个数字,第i行的数字是A[i],表示这个格子能获取的能量

输出
输出结果为一个数字,代表机器人最少需要有多少的初始能量
样例输入
5
1
-2
-1
3
4
样例输出
2

怎么说呢?这是一个大暴力。从最少的初始能量就是保证途中能量最小值为0。也就是说,初始能量就是途中能量最小值的相反数。因此,我们有了时间复杂度为n的算法。唯一的坑就是,数据需要longlong存。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;//不要在意这么多头文件
int main()
{
    long long t,min=0,k,sum=0;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&k);
        sum+=k;
        if(min>sum)min=sum;
    }
    printf("%lld",-min);
    return 0;//不需要解释了
} 

题D:最后一个是谁?题目描述
有n个人围成一圈,顺序排号。从第一个人开始报数(第一个报1,第二个报2……),凡报到m的人退出圈子(下一个人从1开始报),问最后留下的是原来第几号的那位。
输入
多组测试数据 t;
第一行输入t,1<=t<=10.
接下t行,每行两个整数,n,m 1<=n<=1000,1<=m<=1000.
输出
输出t行,每行一个整数。
样例输入
2
468 335
501 170
样例输出
88
393瑟夫问题,不解释。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;//说了不要在意头文件
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,s=0;
        scanf("%d%d",&n,&m);
        for(int i=2;i<=n;i++)
        s=(s+m)%i;
        printf("%d\n",s+1);
    }

} 

题E:三角

题目描述

   将12,······,99个数排成下列形态的三角形。
a
b c
d e
f g h i

其中:a~i分别表示12,······,9中的一个数字,并要求同时满足下列条件:
(1a<f<i;2)b<d, g<h, c<e
(3a+b+d+f=f+g+h+i=i+e+c+a=P

输入
边长之和P
输出
所有满足上述条件的三角形的个数以及其中的一种方案。
若有多种方案输出字典序最小的那种。若无解输出NO。
样例输入
21
样例输出
4
3
2 4
9 6
7 1 5 8

这是一个很坑的问题:由于数据问题,现场没有一个Ac的。赛后改了数据,全场一个两个Ac的。另一个学号还特别诡异。其实,还是一个大暴力。一个数组标记每个数是否使用过了。或者最后判断a+b+c+d+e+f+h+i==55&&a*b*c*d*e*f*g*h*i==1*2*3*4*5*6*7*8*9
或者选择打表。
唯一的问题就是代码很长。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;
int flag[10];
int run(int p)
{
    memset(flag,0,sizeof(flag));//memset是初始化
    int find=0;
    for(int a=1;a<8;a++)//这段是计数
    {
        flag[a]=1;//标记a用过了。下同。
        for(int b=1;b<9;b++)
        if(flag[b]==0)
        {
            flag[b]=1;
            for(int c=1;c<9;c++)
            if(flag[c]==0)
            {
                flag[c]=1;
                for(int f=a+1;f<9;f++)
                if(flag[f]==0)
                {
                    flag[f]=1;
                    for(int i=f+1;i<10;i++)
                    if(flag[i]==0)
                    {
                        flag[i]=1;
                        for(int g=1;g<9;g++)
                        if(flag[g]==0)
                        {
                            flag[g]=1;
                            int d=p-a-b-f,h=p-i-g-f,e=p-i-c-a;
                            if(flag[d]==0&&flag[h]==0&&flag[e]==0&&d!=e&&h!=e&&d!=h&&b<d&&g<h&&c<e&&a<10&&b<10&&c<10&&d<10&&i<10&&f<10&&g<10&&h<10&&e<10)find++;//冗长的判断
                            flag[g]=0;//回复g初始状态,下同
                        }
                        flag[i]=0;
                    }
                    flag[f]=0;
                }
                flag[c]=0;
            }
            flag[b]=0;
        }
        flag[a]=0;
    }
    if(find==0)
    {
        printf("NO\n");
        return 0;
    }
    printf("%d\n",find);
    for(int a=1;a<8;a++)//这段是输出最小字典序
    {
        flag[a]=1;
        for(int b=1;b<9;b++)
        if(flag[b]==0)
        {
            flag[b]=1;
            for(int c=1;c<9;c++)
            if(flag[c]==0)
            {
                flag[c]=1;
                for(int f=a+1;f<9;f++)
                if(flag[f]==0)
                {
                    flag[f]=1;
                    for(int i=f+1;i<10;i++)
                    if(flag[i]==0)
                    {
                        flag[i]=1;
                        for(int g=1;g<9;g++)
                        if(flag[g]==0)
                        {
                            flag[g]=1;
                            int d=p-a-b-f,h=p-i-g-f,e=p-i-c-a;
                            if(flag[d]==0&&flag[h]==0&&flag[e]==0&&b<d&&g<h&&c<e&&a<10&&b<10&&c<10&&d<10&&i<10&&f<10&&g<10&&h<10&&e<10&&d!=e&&h!=e&&d!=h)
                            {
                                printf("%d\n%d %d\n%d %d\n%d %d %d %d\n",a,b,c,d,e,f,g,h,i);
                                return 0;
                            }
                            flag[g]=0;
                        }
                        flag[i]=0;
                    }
                    flag[f]=0;
                }
                flag[c]=0;
            }
            flag[b]=0;
        }
        flag[a]=0;
    }
}
int main()
{
    int p;
    while(scanf("%d",&p)!=EOF)
    run(p);

}

F: 室友A的PY交易

题目描述
CC和TT在宿舍忙着写课设,他们决定由下述游戏的败者去拿外卖:

室友A想一个[1,N]中的数字X,两人轮流猜一个猜一个数字,恰好猜中X的人算负;否则室友A将告诉两人当前猜的数字是比X大还是比X小,这样一来猜测的范围就会变小(下一轮猜的数必须在X所在的那一半区间内)。初始范围是[1,N]。

室友A已经看透了一切,私下告诉了两人X是多少。现在,CC和TT都知道X是多少,且两个人都采取最优策略。若总是CC先猜,求X∈[1,N]可以使TT获胜的X的数量。

输入
第一行一个整数T表示数据组数。

接下来T行,每行一个正整数N1 <= T <= 100000
1 <= N <= 10000000
输出
T行每行一个整数表示答案。
样例输入
1
3
样例输出
1

这是一个博弈论的题目。
先说答案。如果是偶数那么结果是0。如果是奇数,那么结果是1。唯一的结果就是x在1和n最中间。
具体最佳解法就是对称。当对称时,无论TT从左边取多少,CC就从右边取多少。这样取到最后,左右都没有数,TT就必须选择x,然后GG。
因此,对称时必败状态。所以,所有能到必败状态的都是必胜状态。即,不对称是必胜的。然而——
CC先取数。CC可以一下子取到对称。
因此,只有对称是TT能获胜的状态。
时间复杂度1

#include<iostream>
using namespace std;
int main()
{
    int t;int k;
    cin>>t;
    while(t--)
    {

        scanf("%d",&k);
        printf("%d\n",k&1);//这是位运算。。。懒得改了。。。就是判断奇偶。奇输出1,偶0
    }   
}

题 G: 小明的游戏

题目描述
小明喜欢数字,现在小明想把一个数字拆分成若干个奇数的乘积,但他不知道
能不能拆分成功,你能帮帮他么
给你n个数,每个数都在int范围内
0<n<=1e5
单样例
输入
n
x1x2...xn
输出
n行,每行一个输出"YES""NO"(不包括引号)
样例输入
2
3 6
样例输出
YES
NO

还是一个判断奇偶的题目。似乎不用解释了。签到题(虽然数据开始也是错的。。。。)
不会的回去补数学去。

#include<cstdio>
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,s=0;
        scanf("%d",&n);
        if(n&1)printf("YES\n");
        else printf("NO\n");
    }

} 

题 H: 值日生

题目描述
八年级的Vova今天在课堂上值班。上课之后,他走进办公室洗板子,并在上面找到了n号。他问这个数字是什么,数学老师Inna Petrovna回答Vova说,n是一年级学生算术任务的答案。在教科书中,给出了某个正整数 x。n为十进制x加上各位上的数字的 和。

由于数字n很小,Vova很快就猜到了在教科书中可能出现哪个x。现在他想得到一个程序,它将搜索任意值为n的所有合适的x值,或者确定这个x不存在。为Vova写一个这样的程序

输入
第一行包含整数n(1≤  n  ≤10^9)。
输出
在第一行打印一个整数k  表示满足要求的方案

 后k行按照升序打印满足要求的数字

样例输入
21
20
样例输出
1
15
0
提示

15+1+5=21,只有一个满足要求

对于本蒟蒻而已,这个题似乎没有规律。由于n的数字很小(嗯,10^9),所以特别暴力就会TLE(time limit exist)。因此,不能从1开始筛。
读题。一个小于10^9的数字,加上每一位。一共不超过10位,每位小于10,因此x与n的差一定小于100。剩下的,就是100个数分别求其加每一位的值。很暴力吧?
为了省时间,使用了queue。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int find(int n)
{
    queue<int>q;
    int k=n;
    for(int i=k-100;i<k;i++)
    {
        int j=i,p=i;//防止i被破坏
        while(j)
        {
            p+=j%10;
            j/=10;
        }
        if(p==n)q.push(i);
    }
    cout<<q.size()<<endl;//输出大小
    while(!q.empty())
    {
        printf("%d\n",q.front());
        q.pop();
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        find(n);
    }
}

大体就这样了。除了一堆数据问题,这次月赛还是有许多特别水(暴力)的题目的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值