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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM