2018天梯赛第一次训练题解和ac代码

随着评讲的进行代码和题解会逐步放上来

2018天梯赛第一次训练

1001 : 进制转换

Time Limit(Common/Java):1000MS/10000MS     Memory Limit:65536KByte
Total Submit: 78            Accepted: 42

Description

 

输入一个十进制数N,将它转换成R进制数输出。

 

Input

 

输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16)

 

Output

 

为每个测试实例输出转换后的数,每个输出占一行。如果R大于10,则对应的数字规则参考16进制(比如,10用A表示,11用B表示等等)。

 

Sample Input

7 2
23 12
-4 3

Sample Output

111

1B
-11

进制转换属于基础裸题,但是这个题目也还行,要注意0的特殊性

余一下可以获得当前位,除一下把他缩小一下

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string s="0123456789ABCDEF";
int main()
{
    int n,r;
    while(cin>>n>>r)
    {
        string c;
        if(!n)cout<<"0\n";
        else
        {
            if(n<0)cout<<"-",n=-n;
            while(n)c+=s[n%r],n/=r;
            reverse(c.begin(),c.end());
            cout<<c<<"\n";
        }
    }
    return 0;
}

当然这个题目有点简单,还会有给你a进制数x让你转换为b进制数m

数小的话直接把这个用int存一下,然后在转换过来,如果足够长的话要自己写一个模拟的

还有就是一个大数余一个小数的问题,也可以这样按位模拟

for(int i=0; s[i]; ++i)
            ans=ans*10+(s[i]-'0'),ans%=MD;

大数加法也可以的啊ojbk

string add(string s1,string s2){
    string s;
    int len1,len2;
    len1=s1.size()-1; len2=s2.size()-1;
    int i=0,f=0;
    while(len1>-1&&len2>-1){
        int sum=f+(s1[len1--]-'0')+(s2[len2--]-'0');
        s+=sum%10+'0';
        f=sum/10;
    }
    while(len1>-1){
        int sum=f+(s1[len1--]-'0');
        s+=sum%10+'0';
        f=sum/10;
    }
    while(len2>-1){
        int sum=f+(s2[len2--]-'0');
        s+=sum%10+'0';
        f=sum/10;
    }
    if(f) s+='0'+f;
    reverse(s.begin(),s.end());
    return s;
}

其实大数的诸多操作都可以回到模拟上,就是用小学数学列式子计算

 

1003 : lv一样的男子

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 36            Accepted: 28

Description

 

暑假期间苦逼的ACMer在邪恶的宿管中心的安排下,我们这些ACM小菜鸟总算住进了女生大院,可悲的是我们被安排到了TZC的制高点,传说中的女生大院的6楼,(坑爹啊!这是),无奈只好接受事实了,而我们伟大的lv哥,没事总是喜欢在6楼乱扔东西,你想知道为什么,因为他叫lv哥,没办法人家是lv一样的男子,每天扔着扔着,lv哥忽然心血来潮想计算出他扔出的东西到底飞出去多远(落点到楼底的距离),但是高中物理没有学好的lv哥不会计算,想要让你们编个程序帮他解决。

 

 

Input

 

输入有多组数据,每组给你三个数,分别为楼的高度h,出手是的速度v0,速度与水平面的夹角a(0=<a<=90)。重力加速度为g=9.8。

 

Output

 

计算出落点到楼底的距离x,数据保留3位小数。

 

Sample Input

10 10 30
10 10 45
100 0 60

 

Sample Output

17.556m
16.419m
0.000m

Hint

圆周率pi=acos(-1);

这个题只是一道十分简单的高中物理题,可以手推一下公式

或者分成两段进行求解,到最高点

#include <stdio.h>
#include <math.h>
int main()
{
    double h,v,a,pi=acos(-1),t1,t,g=9.8;
    while(~scanf("%lf%lf%lf",&h,&v,&a))
    {
        a*=pi/180;
        t=v*sin(a)/9.8;
        h+=g*t*t/2;
        t+=sqrt(2*h/g);
        printf("%.3fm\n",v*cos(a)*t);
    }
    return 0;
}

再来一道有趣的物理题

L3-1. 非常弹的球 
刚上高一的森森为了学好物理,买了一个“非常弹”的球。虽然说是非常弹的球,其实也就是一般的弹力球而已。森森玩了一会儿弹力球后突然想到,假如他在地上用力弹球,球最远能弹到多远去呢?他不太会,你能帮他解决吗?当然为了刚学习物理的森森,我们对环境做一些简化: 
•假设森森是一个质点,以森森为原点设立坐标轴,则森森位于(0, 0)点。 
•小球质量为w/100 千克(kg),重力加速度为9.8米/秒平方(m/s2)。 
•森森在地上用力弹球的过程可简化为球从(0, 0)点以某个森森选择的角度ang (0 < ang < pi/2) 向第一象限抛出,抛出时假设动能为1000 焦耳(J)。 
•小球在空中仅受重力作用,球纵坐标为0时可视作落地,落地时损失p%动能并反弹。 
•地面可视为刚体,忽略小球形状、空气阻力及摩擦阻力等。

森森为你准备的公式:

动能公式:E = m * v^2 / 2 
牛顿力学公式:F = m * a 
重力:G = m * g 
其中: 
E - 动能,单位为“焦耳” 
m - 质量,单位为“千克” 
v - 速度,单位为“米/秒” 
a - 加速度,单位为“米/秒平方” 
g - 重力加速度

输入格式:

输入在一行中给出两个整数:1 <= w <= 1000 和 1 <= p <= 100,分别表示放大100倍的小球质量、以及损失动力的百分比p。

输出格式:

在一行输出最远的投掷距离,保留3位小数。 
输入样例:100 90

输出样例:226.757 
简单推一下,v^2=2E/m 
s=vt=2vcosθ/g*vsinθ=v^2sin2θ/g 
sin2θ最大值是1,也就是θ为45°

#include<stdio.h>
#include<cmath>
int main()
{
    double w,p,e;
    scanf("%lf%lf",&w,&p);
    e=2000*100/w;
    p=1-p/100;
    double s=0;
    while(e>0.000001)
    {
        s+=e/9.8;
        e=e*p;
    }
    printf("%.3f",s);
    return 0;
}

 

1002 : 复习时间

时间限制(普通/Java):1000MS/10000MS     内存限制:65536KByte
总提交: 48            测试通过: 46

描述

为了能过个好年,xhd开始复习了,于是每天晚上背着书往教室跑。为了追求更高的效率,xhd要根据难度值来选择合适的课程进行复习,复习后一门课的效率为前一门课之间的难度差的平方,而复习第一门课的效率为100和这门课的难度差的平方。xhd这学期选了n门课,但是一晚上他最多只能复习m门课,请问他复习单独一门课程的最高效率值是多少?

输入

输入数据的第一行是一个数据T,表示有T组数据。
每组数据的第一行是两个整数n(1 <= n <= 40),m(1 <= m <= n)。
接着有n行,每行有一个正整数a(1 <= a <= 100),表示这门课的难度值。

输出

对于每组输入数据,输出一个整数,表示最高效率值。

样例输入

2
2 2
52
25
12 5
89
64
6
43
56
72
92
23
20
22
37
31

样例输出

5625
8836

B就是找(100-x)*(100-x)最大的,我找到最小的x即可

#include <stdio.h>
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,s=100;
        scanf("%d%d",&n,&m);
        for(int i=0,x;i<n;i++)
        {
            scanf("%d",&x);
            if(s>x)s=x;
        }
        printf("%d\n",(100-s)*(100-s));
    }
    return 0;
}

1004 : 集合运算

Time Limit(Common/Java):1000MS/10000MS     Memory Limit:65536KByte
Total Submit: 53            Accepted: 23

Description

给定两个集合A和B的所有元素,计算它们的交、并、差集。

Input

输入数据有多组,第一行为数据的组数T,接下来有2T行,每组数据占2行,每行有若干个整数,第一行的所有整数构成集合A,第二行的所有整数构成集合B,分别用空格分隔。A和B最多分别不超过100个元素。

Output

输出A、B的交、并、差集中的所有元素(以递增顺序)。每个集合占一行,数据元素之间用空格分隔。

Sample Input

1
0 1 2 3 4 5 6 7 8 8
3 6 8 9

Sample Output

3 6 8
0 1 2 3 4 5 6 7 8 9
0 1 2 4 5 7

分别计算交并和差,py写起来很简单

x=set()  
x & y # 交集  
x | y # 并集  
x - y # 差集  

c++里面有set这样的集合

A存和集,B存交集,D存差集,C作为辅助集

#include<iostream>
#include<sstream>
#include<string>
#include<set>
using namespace std;
set<int>::iterator it;
void la(set<int> &s)
{
    int f=0;
    for(it=s.begin(); it!=s.end(); it++)
        cout<<(f?" ":"")<<*it,f=1;
    cout<<"\n";
}
int main()
{
    int T,x;
    cin>>T;
    string s;
    getline(cin,s);
    while(T--)
    {
        set<int>A,B,C,D;
        getline(cin,s);
        stringstream ss(s);
        while(ss>>x)
            A.insert(x),D.insert(x),C.insert(x);
        getline(cin,s);
        stringstream ss1(s);
        while(ss1>>x)
        {
            if(C.count(x))B.insert(x),D.erase(x);
            A.insert(x);
        }
        la(B),la(A),la(D);
    }
    return 0;
}

 

 当然也可以用algorithm的函数

        set_intersection(a.begin(),a.end(),b.begin(),b.end(),inserter(c1,c1.begin()));
        set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(c2,c2.begin()));
        set_difference(a.begin(),a.end(),b.begin(),b.end(),inserter(c3,c3.begin()));

其实也可以自己模拟的,sort什么的,我嫌弃他浪费时间,不好写,那个读取一行也可以gets然后sscanf

1007 : 最长连续子序列

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 26            Accepted: 17

Description

 

给定一系列非负整数,求最长的连续子序列,使其和是7的倍数。

 

Input

 

第一行为正整数N(1<=N<=50000),接下来有N行,每行有一个非负整数,所有整数不大于10^6。

 

Output

 

如果存在连续子序列,其和为7的倍数,则输出子序列长度,如果不存在则输出0。

 

Sample Input

7
3
5
1
6
2
14
10

Sample Output

5

这个可以先想到n^3的做法,就是枚举起点终点,然后把这段求和

前缀和优化一下变成n^2,也就是只需要枚举起点终点

然后你观察下能被除的条件,就是两个的余数相同,我只要存一下第一次出现的余数就好了,但是会有有一个数能被7整除,这个需要加上的

#include <stdio.h>
int a[7],b[7],n,s=0,mi;
int main()
{
    scanf("%d",&n);
    for(int i=1,p; i<=n; i++)
    {
        scanf("%d",&p),s=(s+p)%7,b[s]=i;
        if(!a[s]&&s)a[s]=i;
    }
    for(int i=0; i<7; i++)
        if(b[i]-a[i]>mi)mi=b[i]-a[i];
    printf("%d",mi);
    return 0;
}

1005 : AcGhost去逛街了~

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 112            Accepted: 26

Description

 

话说某天天气很好,AcGhost队就想去逛街了。逛着逛着dongsaiyuan就看见前面的摊子上有卖手链的,只见那手链由n颗珠子串成,很漂亮。dongsaiyuan灵机一动,想根据这串手链给两位哥哥出道题目。如果有一小串的珠链,那你能判断这珠链是否是这手链的一部分吗??两位哥哥一下子就想出来了,那你呢?

 

 

Input

 

输入数据有多组,每组输入两串字符串str和s,分别代表手链和珠链,其中字符全为小写字母,字符串的长度也不超过1000010

 

Output

 

若珠链是手链的一部分,输出YES,否则输出NO

 

Sample Input

2
abc bc
abc acb

Sample Output

YES
NO

A是一个项链,构成环,但是abc其实有abc bca cab(还有反转串?),然后你直接把A相加看看有没有B(有没有B的反转串?)

 

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        string a,b;
        cin>>a>>b;
        a=a+a;
        if(a.find(b)!=-1&&a.length()/2>=b.length())
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

新版本的strstr是KMP做的会很快,他返回的是char的指针数组,可以这样写char *p=strstr(a,b);

但是我的strcat导致我一直RE,这个函数要求src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串,所以我要用函数必须借助中间变量

#include<cstdio>
#include<cstring>
const int N=1e6+10;
char a[N+N],b[N],c[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%s",a,b);
        if(strlen(a)<strlen(b))
            printf("NO\n");
        else
            strcpy(c,a),strcat(a,c),printf("%s\n",strstr(a,b)==NULL?"NO":"YES");
    }
    return 0;
}

 

1006 : 表达式求值

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 17            测试通过: 6

描述

 

Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20,23)的值是20 ,add(10,98) 的值是108等等。经过训练,Dr.Kong设计的机器人卡多甚至会计算一种嵌套的更复杂的表达式。

假设表达式可以简单定义为:

1. 一个正的十进制数 x 是一个表达式。

2. 如果 x 和 y 是 表达式,则 函数min(x,y )也是表达式,其值为x,y 中的最小数。

3. 如果 x 和 y 是 表达式,则 函数max(x,y )也是表达式,其值为x,y 中的最大数。

4.如果 x 和 y 是 表达式,则 函数add(x,y )也是表达式,其值为x,y 之和。

例如, 表达式 add(max(add(1,2),7) 的值为 7。

请你编写程序,对于给定的一组表达式,帮助 Dr.Kong 算出正确答案,以便校对卡多计算的正误。

 

输入

 

第一行: N        表示要计算的表达式个数 (1≤ N ≤ 10) 

接下来有N行,    每行是一个字符串,表示待求值的表达式

(表达式中不会有多余的空格,每行不超过300个字符,表达式中出现的十进制数都不

超过1000。)

 

输出

 

输出有N行,每一行对应一个表达式的值。

 

样例输入

 

3
add(1,2)
max(1,999)
add(min(1,1000),add(100,99))

样例输出

 

3
999
200

 

#include <stdio.h>
char str[310];
int f=0;
int min(int x,int y)
{return x>y?y:x;}
int max(int x,int y)
{return x>y?x:y;}
int fun()
{
    int v,n;
    switch(str[f])
    {
    case 'm':
        f+=3;
        if(str[f-2]=='i')
            return min(fun(),fun());
        else
            return max(fun(),fun());
        break;
    case 'a':
        f+=3;
        return fun()+fun();
        break;
    case ',':
    case '(':
    case ')':
        f++;
        return fun();
        break;
    default:
        sscanf(str+f,"%d%n",&v,&n);
        f+=n;
        return v;
        break;
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",str);
        printf("%d\n",fun()); 
        f=0;
    }    
    return 0;
}

2950: 逻辑表达式求解 分享至QQ空间

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 1504            Accepted:485

Description

 

在离散数学中,∩和∪代表的是与、或的逻辑运算,给你一串只有∩和∪两种运算符的0,1表达式,求其结果。
这里规定∩符号为字符^,即数字六上档键;
∪符号为v,小写的字母v

 

Input

 

第一行一个整数n,表示有n个测试数据
以下n行每组数据,第一行一个整数t,表示这个表达式有t个字符
第二行为这个表达式,长度为t个字符,保证字符不超过10000个

 

Output

 

请输出每组表达式子的最终结果

 

Sample Input

2
5
1^1v0
3
0^1

Sample Output

 

1
0

优先级不同

operator的各种问题

#include<stdio.h>
#include<stack>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        stack<char>f;
        char a[10001];
        scanf("%d%s",&n,a);
        f.push(a[0]);
        for(int i=1;i<n;i+=2)
        {
            if(a[i]=='v')
            {
              f.push(a[i+1]);    
            }
            else
            {
                if(!f.empty())
                {
                    char s=f.top();f.pop();
                    if(s=='1'&&a[i+1]=='1')
                    f.push('1');
                    else f.push('0');
                }
            } 
        }
        int c=0;
        while(!f.empty())
        {
            if(f.top()=='1')c=1;
            f.pop();
        }
        if(c)printf("1\n");
        else printf("0\n");
    }
}

xjb优化的

#include<stdio.h>
char a[10005];
int s[10005],tot,T,n;
void la()
{
    for(int i=0;i<tot;i++)
    if(s[i]){puts("1");return;}
    puts("0");
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        tot=0;
        scanf("%d%s",&n,a);
        s[tot++]=a[0]-'0';
        for(int i=1;i<n;i+=2)
            if(a[i]=='v')
            s[tot++]=a[i+1]-'0';
            else if(tot)
            s[tot-1]&=a[i+1]-'0';
        la();
    }
}

 根据状态设置两个标记变量的

#include<stdio.h>
bool s,ans;
int T,n;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        char c,c1;
        scanf("%d",&n);
        getchar(),c=getchar(),c-='0',s=c,ans=0;
        for(int i=1; i<n; i+=2)
        {
            c=getchar(),c1=getchar()-'0';
            if(c=='v')ans|=s,s=c1;
            else s&=c1;
        }
        printf("%d\n",ans|s);
    }
}

 

1008 : 马虎的算式

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 25            Accepted: 13

Description

 

logx是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。

有一次,老师出的题目是:36 x 495 = ?

他却给抄成了:396 x 45 = ?

但结果却很戏剧性,他的答案竟然是对的!!

因为 36 * 495 = 396 * 45 = 17820

类似这样的巧合情况可能还有很多,比如:27 * 594 = 297 * 54

假设 a b c d e 代表1~9不同的5个数字(注意是各不相同的数字,且不含0)

现在限定a>=x1,b>=x2,c>=x3,d>=x4,e>=x5,求:

能满足形如: ab * cde = adb * ce 这样的算式一共有多少 种呢?

请输出所有算式,并且要求按abcde的字典序从小到大输出ab * cde = ?

 

Input

 

输入有多组数据,不超过20组。

每组数据占一行,每行为5个整数x1,x2,x3,x4,x5(1<=x1,x2,x3,x4,x5<=9)。

 

Output

 

输出所有符合要求的等式,每个等式一行。

 

Sample Input

 9 9 9 9 9

Sample Output

 99 * 999 = 98901

a>=x1,b>=x2,c>=x3,d>=x4,e>=x5,所以是一个五层循环

 ab * cde = adb * ce就是直接判断

#include <iostream>
using namespace std;
int main()
{
    int a,b,c,d,e;
    while(cin>>a>>b>>c>>d>>e)
    {
        for(int i=a; i<10; i++)
            for(int j=b; j<10; j++)
                for(int k=c; k<10; k++)
                    for(int l=d; l<10; l++)
                        for(int m=e; m<10; m++)
                            if((i*10+j)*(k*100+l*10+m)==(i*100+l*10+j)*(k*10+m))
                                cout<<i*10+j<<" * "<<k*100+l*10+m<<" = "<<(i*10+j)*(k*100+l*10+m)<<"\n";
    }
    return 0;
}

1009 : 最大素数

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 49            Accepted: 21

Description

 

给定一个数n,问是否可以按从左到右的顺序从其中取出连续的若干位组合成一个素数(大于1,且只能被1和自身整除的数称为素数),若有多种可能,则取所有可能的数中最大的一个。

如在1234中,我们可以取1234,123,234,12,23,34,1,2,3,4,发现素数有2,3,23,其中最大的素数为23。

 

Input

 

输入数据有多组,每组占一行,每行一个正整数n(2<=n<=2147483647)。

 

Output

 

对于每组输出,若存在,则输出最大的素数,否则输出None

 

Sample Input

1234

Sample Output

 23


给定的数是2到int以内的,但是其中的一位还是可能是1。

我把每个串都枚举一次,然后sscanf得到这个int值,直接判断是不是素数就好了,这里用了最朴素的sqrt(n)的算法

#include<stdio.h>
#include<math.h>
#include<string.h>
int fun(int n)
{
    if(n==1)return 0;
    for(int i=2; i<=sqrt(n); i++)
        if(n%i==0)return 0;
    return 1;
}
int main()
{
    char a[20],s[20];
    while(~scanf("%s",a))
    {
        int len=strlen(a),n,ma=-1;
        for(int i=0; a[i]; i++)
        {
            int k=0;
            for(int j=i; j<len; j++)
            {
                s[k++]=a[j],s[k]=0;
                sscanf(s,"%d",&n);
                if(fun(n)&&ma<n)ma=n;
            }
        }
        if(ma==-1)
            printf("None\n");
        else
            printf("%d\n",ma);
    }
    return 0;
}

素数筛选常用算法为埃筛(埃拉托斯特尼筛法)

#include<string>
#include<iostream>
using namespace std;
const int N=1e7+5;
int f[N];
void prime()
{
    f[0]=f[1]=1;
    for(int i=2; i<N; i++)
    {
        if(f[i]) continue;
        for(int j=i+i; j<N; j+=i)f[j]=1;
    }
}
int main()
{
    prime();
    for(int i=0;i<100;i++)
        if(!f[i])cout<<i<<"\n";
    return 0;
}

加速筛选

#include<string>
#include<iostream>
using namespace std;
const int N=1e7+5;
int f[N],pri[N],tot;
void prime()
{
    f[1]=1;
    for(int i=2; i<N; i++)
    {
        if(!f[i]) pri[++tot]=i;
        for(int j=1;i*pri[j]<N&&j<=tot; j++)
        {
            f[i*pri[j]]=1;
            if(i%pri[j]==0) break;
        }
    }
}
int main()
{
    prime();
    for(int i=1;i<100;i++)
        cout<<pri[i]<<"\n";
    return 0;
}

 

1010 : 终曲

时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte
总提交: 27            测试通过: 10

描述

 

最后的挑战终于到了!
站在yifenfei和MM面前的只剩下邪恶的大魔王lemon一人了!战胜他,yifenfei就能顺利救出MM。
Yifenfei和魔王lemon的挑战很简单:由lemon给出三个字符串,然后要yifenfei说出第一串的某个子串,要求该子串长度最小,并且同时包含第2个串和第3个串。
特别地,如果有多个这样的子串,则请输出字母序最小的一个。

 

输入

 

输入数据首先是一个整数C,表示测试数据有C组;
接着是C组数据,每组包含三行字符串,第一个字符串长度大于1小于100
后面两个串的长度大于1且小于10
 

 

输出

 

请对应每组输入数据输出满足条件的最短子串;
如果没有,请输出 No
 

 

样例输入

2
abcd
ab
bc
abc
ab
bd

样例输出

abc
No

枚举每一个子串,然后去判断

#include<string>
#include<iostream>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string s1,s2,s3,s;
        cin>>s1>>s2>>s3;
        for(int i=0; i<s1[i]; i++)
            for(int j=i; j<s1[j]; j++)
            {
                string t=s1.substr(i,j-i+1);
                if(t.find(s2)!=-1&&t.find(s3)!=-1&&(s==""||t.size()<s.size()||t.size()==s.size()&&t<s))
                    s=t;
            }
        cout<<(s==""?"No":s)<<"\n";
    }
    return 0;
}

1011 : More Beautiful

Time Limit(Common/Java):1000MS/10000MS     Memory Limit:65536KByte
Total Submit: 20            Accepted: 4

Description

 

当老师不容易,尤其是当小学的老师更难:现在的小朋友做作业喜欢滥用括号。
虽然不影响计算结果,但不够美观,容易出错,而且可读性差。但又不能一棒子打死,也许他们就是将来的“陈景润”呢!
为了减轻老师的工作,不至于他们工作到深夜,我们来写个程序把小朋友的作业做一下简单地处理,去掉那些多余的括号。
为了简化问题,所有式子里只存在小括号,运算符号包括+(加)、-(减)、*(乘)、/(除)、^(幂)。
注意:去掉多余的小括号不是指运算结果一样就可以。
比如:(1+2)^1 = 3。虽然把括号去掉1+2^1也等于3,但我们说这个括号不能去。
但如:1+(2+3) = 1+2+3只要是允许的,因为加法是满足交换律和结合律的。

 

Input

 

输入包括多组测试数据。
每组测试数据为一行算术表达式,只包括正整数和运算符号,长度小于16。
输入以#行结束,该行不做处理。

 

Output

 

对应每组数据输入都有一行输出。
输出去掉多余的括号后的表达式。

 

Sample Input

2*(1*(4*3))
3*(2*(4/1))
((4*2)/1)*3
(1)+(2)+(3)+(4)
1-(2-(3-4))
((3*2)*4)^1
#

Sample Output

2*1*4*3
3*2*4/1
4*2/1*3
1+2+3+4
1-(2-(3-4))
(3*2*4)^1

这个有种更复杂的题目就是还有多余的括号,当然这个也能出成一道题,就是括号旁边也还是括号,这个比较简单,可以直接处理掉,当然也要按照栈的思想

for(int i=0; s[i]; i++)
    if(s[i]=='(')a[tot++]=i;
    else if(s[i]==')')
    {
        if(s[i+1]==')'&&s[a[tot-1]-1]=='(')
            b[i]=b[a[--tot]]=1;
    }

括号能去不能去也就是优先级的问题,还有+ *这种特殊的情况,if情况写够就行了

#include <stdio.h>
#include <string.h>
char s[18];
int a[18],has[255],b[18],f[18];
int main()
{
    has['-']=1,has['*']=2,has['/']=3,has['^']=4;
    while(scanf("%s",s),s[0]!='#')
    {
        int tot=0;
        memset(b,0,sizeof b),memset(f,0,sizeof f),tot=1;
        for(int i=0; s[i]; i++)
            if(s[i]=='(')a[tot++]=i;
            else if(s[i]==')')
            {
                --tot;
                if((f[tot-1]<f[tot]||f[tot-1]==f[tot]&&(f[tot]==0||f[tot]==2))&&(f[tot]>=has[s[i+1]]||f[tot]==2&&has[s[i+1]]==3))
                    b[i]=b[a[tot]]=1,f[tot]=0;
            }
            else if(has[s[i]]>f[tot-1])f[tot-1]=has[s[i]];
        for(int i=0; s[i]; i++)
            if(!b[i])printf("%c",s[i]);
        putchar(10);
    }
    return 0;
}

5269: 玛祖游戏 分享至QQ空间

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 90            Accepted:44

Description

 

 

玛祖是一款非常经典的游戏,游戏的角色是一只青蛙,青蛙每次可以吐出一颗珠子,如果将珠子吐到场景中相同颜色的珠子旁边(称为击中),当三个或者三个以上的同颜色珠子在一起的时候便可以消掉,如果消掉后还有相同颜色的珠子,则可以继续消除(我们称为连击)。

YuYu也很喜欢这个游戏,而且希望连击次数越多越好,因此每次当她发现击中某种颜色的珠子能达到最大连击次数时,她总是等待该颜色出现!

现在给定已经出现在游戏场景中的珠子队列,问瑜瑜可能达到的最大连击次数是多少?

为了简化问题,我们的游戏规则是只要有两个颜色相同的珠子连在一起都可以消掉。

 

 

Input

 

 

输入数据有多组,每组占一行,每行一个由小写字母组成的字符串,长度不超过100000,表示游戏场景中的珠子队列,每个字母代表一种颜色。

 

 

Output

 

 

每组输出一个数字,表示最大的连击次数,该结果不会超过10000。

 

 

Sample Input

b
aaabaaaa
ccccccccaaaaaaabbbdddddddeeeeeeeddddddbbbaaaaaaccccc

Sample Output

1
2
5

这个祖玛是修改版的,两个就可以消除,所以先预处理得到单个字母的字符串。你打进去一个,如果是回文的话就一直连击啊。

#include <stdio.h>
char s[100005];
int main() {
    char c;
    while((s[0]=getchar())!=EOF) {
        int f=0,ma=1;
        while((c=getchar())!='\n'){
            if(c!=s[f])
            s[++f]=c;
        }
        for(int i=1; i<f; i++) {
            int ans=1;
            int l=i-1,r=i+1;
            while(l>=0&&r<=f) {
                if(s[l]!=s[r])
                    break;
                l--;
                r++;
                ans++;
            }
            if(ans>ma)ma=ans;
        }
        printf("%d\n",ma);
    }
    return 0;
}

dfs生成回文串

void DFS(int d,int t,string s) {
    if(d==t/2+(t%2) +1 ) {
        int num=0;
        for(int i=0;i<s.length();i++) num=num*10+(s[i]-'0');
        if(t%2==0) for(int i=s.length()-1;i>=0;i--) num=num*10+(s[i]-'0');
        else for(int i=s.length()-2;i>=0;i--) num=num*10+(s[i]-'0');
        if(a<=num&&num<=b&&pri(num)) V[f++]=num;
        return;
    }
    for(int i=(d==1)?1:0;i<=9;i++) {
        if(d==1&&i%2==0) continue;
        string p=c.substr(i,1);
        DFS(d+1,t,s+p);
    }
}

 

1012 : 判断正确

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 33            Accepted: 13

Description

 

 

小航比较粗心,判断他写的表达式是否正确。

 

 

Input

 

 

多组数据,直到文件结束。每行输入  a 运算符号 b 关系符号  c ,(0<=a,b,c<=9),用英文字母表示。

运算符号 "+", "-", "*" or "/"     and    关系符号  ">", "<" ,"=","<=" or ">="。

 

 

Output

 

 

首先若出现除零的情况,输出expression  false,否则若表达式正确并且精确,输出true,再其次表达式不正确的话输出正确并且精确的表达式。输出格式参照样例。

 

 

 

Sample Input

one+two=three
two-three=zero
five/four>one
nine*nine<=zero

Sample Output

true
two-three < zero
true
nine*nine > zero

Hint

例如4/4>=1是正确的,但不是精确地,正确并且精确地是4/4=1。

RE了两发,神奇,是getline的锅啊

我的代码应该是最短的,我的思路就是先创建1对1的映射,其实也是写麻烦了,但是我只用了stl,正好讲解一发stl啊

中间有一个会产生浮点数的操作,所以我把除变乘了,我标记下特殊符号的位置以及是否为>=进行模拟就非常短了

#include <iostream>
#include <string>
#include <map>
using namespace std;
map<string,int>M;
int a[128],x,y,z,b,c,f;
string s;
char t;
int main()
{
    M["zero"]=0,M["one"]=1,M["two"]=2,M["three"]=3,M["four"]=4,M["five"]=5,M["six"]=6,M["seven"]=7,M["eight"]=8,M["nine"]=9,a['+']=a['-']=a['*']=a['/']=1,a['=']=a['>']=a['<']=2;
    while(cin>>s)
    {
        for(int i=0; s[i]; i++)
            if(a[s[i]]==1)x=M[s.substr(0,i)],b=i;
            else if(a[s[i]]==2)
            {
                y=M[s.substr(b+1,i-b-1)],c=i;
                if(s[c+1]=='=')z=M[s.substr(c+2)],f=0;
                else z=M[s.substr(c+1)],f=1;
                break;
            }
        if(y==0&&s[b]=='/')cout<<"expression  false\n";
        else
        {
            if(s[b]=='+') x+=y;
            else if(s[b]=='-') x-=y;
            else if(s[b]=='*') x*=y;
            else  z*=y;
            if(x==z) t='=';
            else if(x>z)  t='>';
            else t='<';
            if(t==s[c]&&f)cout<<"true\n";
            else cout<<s.substr(0,c)<<" "<<t<<" "<<s.substr(c+2-f)<<"\n";
        }
    }
    return 0;
}

1013 : 生活大爆炸版石头剪刀布

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 29            Accepted: 22

Description

 

石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一 样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种石头剪刀布的升级版游戏。

升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势:

斯波克:《星际迷航》主角之一。

蜥蜴人:《星际迷航》中的反面角色。

这五种手势的胜负关系如表一所示,表中列出的是甲对乙的游戏结果。

甲\乙剪刀石头蜥蜴人斯波克
剪刀
石头 ×
× ×
蜥蜴人 × × ×
斯波克 × × × ×

现在,小 A 和小 B 尝试玩这种升级版的猜拳游戏。已知他们的出拳都是有周期性规律的,但周期长度不一定相等。例如:如果小A以“石头-布-石头-剪刀-蜥蜴人-斯波克”长度为 6 的周期出拳,那么他的出拳序列就是“石头-布-石头-剪刀-蜥蜴人-斯波克-石头-布-石头-剪刀-蜥蜴人-斯波克-......”,而如果小B以“剪刀-石头-布-斯波克-蜥蜴人”长度为 5 的周期出拳,那么他出拳的序列就是“剪刀-石头-布-斯波克-蜥蜴人-剪刀-石头-布-斯波克-蜥蜴人-......”

已知小 A 和小 B 一共进行 N 次猜拳。每一次赢的人得 1 分,输的得 0 分;平局两人都得 0 分。现请你统计 N 次猜拳结束之后两人的得分。

 

 

Input

 

第一行包含三个整数:N,NA,NB,分别表示共进行 N 次猜拳、小 A 出拳的周期长度,小 B 出拳的周期长度。数与数之间以一个空格分隔。

第二行包含 NA 个整数,表示小 A 出拳的规律,第三行包含 NB 个整数,表示小 B 出拳的规律。其中,0 表示“剪刀”,1 表示“石头”,2 表示“布”,3 表示“蜥蜴人”,4 表示“斯波克”。数与数之间以一个空格分隔。

 

 

Output

 

输出一行,包含两个整数,以一个空格分隔,分别表示小 A、小 B 的得分。

 

Sample Input

10 5 6
0 1 2 3 4
0 3 4 2 1 0

Sample Output

 6 2

都说是周期了,那就按照周期模拟好了

#include<stdio.h>
int s[5][5]= {0,0,1,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,1,1,0,0,0};
int a[1000],b[1000];
int main()
{
    int n,na,nb,sa=0,sb=0;
    scanf("%d%d%d",&n,&na,&nb);
    for(int i=0; i<na; i++)scanf("%d",&a[i]);
    for(int i=0; i<nb; i++)scanf("%d",&b[i]);
    for(int i=0; i<n; i++)sa+=s[a[i%na]][b[i%nb]],sb+=s[b[i%nb]][a[i%na]];
    printf("%d %d\n",sa,sb);
}

1014 : 计算器的改良

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 46            Accepted: 12

Description

 

NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能。实验室将这个任务交给了一个刚进入的新手ZL先生。为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例:

 

4+3x+8

6a-5+1=2-2a

  -5+12y=0

 

ZL先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及+、-、=这三个数学符号(当然,符号“-”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。

 

编写程序,解输入的一元一次方程, 将解方程的结果(精确至小数点后三位)输出至屏幕。

 

你可假设对键入的方程的正确性的判断是由另一个程序员在做,或者说可认为键入的一元一次方程均为合法的,且有唯一实数解。

 

 

Input

 

一个一元一次方程(见上,长度不超过100)

 

Output

 

方程的解,精确到小数点后三位.

 

Sample Input

 6a-5+1=2-2a

Sample Output

a=0.750

我要尽量把代码写的短一点,就把模拟写得简单点,我先标记在左边还是右边

把字母挪到一边,数字挪到一边,就是一加一减,还有乘上符号,当时没有考虑系数为0和有等于号这个数就要回到正号,把细节考虑完整就好

#include<stdio.h>
char s[105],c;
int main()
{
    scanf("%s",s);
    int x=0,n=0,f=1,k=1;
    for(int i=0; s[i]; i++)
    {
        if(s[i]=='=')  f=-1,k=1;
        else if(s[i]=='-')k=-1;
        else if(s[i]=='+')k=1;
        else
        {
            int a=0;
            while(s[i]>='0'&&s[i]<='9')a=a*10+s[i++]-'0';
            if(s[i]>='a'&&s[i]<='z')
                c=s[i],x-=f*k*(a==0?1:a);
            else
                n+=f*k*a,i--;
        }
    }
    printf("%c=%.3f",c,n*1.0/x);
}

1015 : 近似回文词

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 16            Accepted: 3

Description

 

输入一行文本,输出最长近似回文词连续子串。所谓近似回文词是指满足以下条件的字符串:
1. S以字母开头,字母结尾
2. a(S)和b(S)最多有2k个位置不同,其中a(S)是S删除所有非字母字符并且把所有字母转化成小写之后得到的串,b(S)是a(S)的逆序串。
比如当k=1时,Race cat是一个近似回文词,因为a(S)=racecat和b(S)=tacecar只有2个位置不同。

 

 

Input

 

输入包含不超过25组数据,每组数据包含两行。第一行是整数k(0<=k<=200),第二行为字符串S,包含至少一个字母但不超过1000个字符(换行符不算)。S只包含字符、空格和其他可打印字符(比如逗号,句号),并且不会以空白字符开头。

 

Output

 

对于每组测试数据,输出最长近似回文子串的长度和起始位置(S的第一个字符是位置1)。如果有多个最长近似回文子串解,起始位置应尽量小。

 

Sample Input

 

1
Wow, it is a Race cat!
0
abcdefg
0
Kitty: Madam, I'm adam.

Sample Output

 

Case 1: 8 3
Case 2: 1 1
Case 3: 15 8

近似回文就是只用处理字母了,而且大小写不分了,向外扩展就可以了

#include<stdio.h>
#include<ctype.h>
const int N=1005;
char s[N];
int a[N];
int main()
{
    int k,T=1;
    while(~scanf("%d",&k))
    {
        getchar();
        gets(s);
        int ma=-1,b=-1,m=0;
        for(int i=0; s[i]; i++)
            if(isalpha(s[i]))a[m]=i,s[m++]=tolower(s[i]);
        for(int i=0; i<m; i++)
        {
            int t,j;
            for(t=j=0; i-j>=0&&i+j<m; j++)
                if(s[i-j]!=s[i+j])
                {
                    if(t==k)break;
                    else t++;
                }
            if(a[i+j-1]-a[i-j+1]>ma)
                ma=a[i+j-1]-a[i-j+1],b=a[i-j+1];
            for(t=j=0; i-j>=0&&i+j+1<m; j++)
                if(s[i-j]!=s[i+j+1])
                {
                    if(t==k)break;
                    else t++;
                }
            if(j>0&&a[i+j]-a[i-j+1]>ma)
                ma=a[i+j]-a[i-j+1],b=a[i-j+1];
        }
        printf("Case %d: %d %d\n",T++,ma+1,b+1);
    }
    return 0;
}

 

posted @ 2018-03-05 12:33  暴力都不会的蒟蒻  阅读(2409)  评论(1编辑  收藏  举报