1. 程式人生 > >演算法筆記 3.1 codeup課後題

演算法筆記 3.1 codeup課後題

問題 A: 剩下的樹

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

有一個長度為整數L(1<=L<=10000)的馬路,可以想象成數軸上長度為L的一個線段,起點是座標原點,在每個整數座標點有一棵樹,即在0,1,2,...,L共L+1個位置上有L+1棵樹。     現在要移走一些樹,移走的樹的區間用一對數字表示,如 100 200表示移走從100到200之間(包括端點)所有的樹。     可能有M(1<=M<=100)個區間,區間之間可能有重疊。現在要求移走所有區間的樹之後剩下的樹的個數。

輸入

兩個整數L(1<=L<=10000)和M(1<=M<=100)。     接下來有M組整數,每組有一對數字。

輸出

 可能有多組輸入資料,對於每組輸入資料,輸出一個數,表示移走所有區間的樹之後剩下的樹的個數。

樣例輸入

4 2
1 2
0 2
11 2
1 5
4 7
0 0

樣例輸出

2
5

程式碼:

#include <iostream>
#include<algorithm>
using namespace std;

const int MAXN=10010;
int tree[MAXN];


int main()
{
    int L,M;
    int a,b;
    while(cin>>L>>M){
        if(L==0&&M==0){
            break;
        }
        fill(tree,tree+L+1,1);
        for(int i=0;i<M;i++){
            cin>>a>>b;
            for(int i=a;i<=b;i++){
                if(tree[i]){
                    tree[i]=0;
                }
            }
        }
        int sum=0;
        for(int i=0;i<=L;i++){
            sum+=tree[i];
        }
        cout<<sum<<endl;
    }
    return 0;
}

問題 B: A+B

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

給定兩個整數A和B,其表示形式是:從個位開始,每三位數用逗號","隔開。 現在請計算A+B的結果,並以正常形式輸出。

輸入

輸入包含多組資料資料,每組資料佔一行,由兩個整數A和B組成(-10^9 < A,B < 10^9)。

輸出

請計算A+B的結果,並以正常形式輸出,每組資料佔一行。

樣例輸入

-234,567,890 123,456,789
1,234 2,345,678

樣例輸出

-111111101
2346912

程式碼:

#include <iostream>
#include<cstdio>
#include<string>
using namespace std;

typedef long long ll;
string s1,s2;

ll toLong(string s){
    ll ans;
    char a[20];
    int len=s.length();
    int k=0;
    for(int i=0;i<len;i++){
        if(s[i]!=','){
            a[k++]=s[i];
        }
    }
    a[k]='\0';
    sscanf(a,"%lld",&ans);//codeblock 波浪線報錯 有時不用管他
    return ans;
}

int main()
{
    while(cin>>s1>>s2){
        cout<<toLong(s1)+toLong(s2)<<endl;
    }
    return 0;
}

問題 C: 特殊乘法

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

寫個演算法,對2個小於1000000000的輸入,求結果。特殊乘法舉例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5

輸入

 兩個小於1000000000的數

輸出

 輸入可能有多組資料,對於每一組資料,輸出Input中的兩個數按照題目要求的方法進行運算後得到的結果。

樣例輸入

24 65
42 66666
3 67

樣例輸出

66
180
39

程式碼:

#include <iostream>
#include<string>
using namespace std;
typedef long long ll;
string s1,s2;

ll Sum(string s){
    ll res=0;
    for(int i=0;i<s.length();i++){
        res+=(s[i]-'0');
    }
    return res;
}


int main()
{
    while(cin>>s1>>s2){
        cout<<Sum(s1)*Sum(s2)<<endl;
    }

    return 0;
}

問題 D: 比較奇偶數個數

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

第一行輸入一個數,為n,第二行輸入n個數,這n個數中,如果偶數比奇數多,輸出NO,否則輸出YES。

輸入

輸入有多組資料。 每組輸入n,然後輸入n個整數(1<=n<=1000)。

輸出

如果偶數比奇數多,輸出NO,否則輸出YES。

樣例輸入

1
67 
7
0 69 24 78 58 62 64 

樣例輸出

YES
NO

程式碼:

#include <iostream>
#include<cstring>
using namespace std;
int main()
{
    int n;
    int a[1010];
    int even,odd;
    while(cin>>n){
        memset(a,0,sizeof(a));
        even=0;
        odd=0;
        for(int i=0;i<n;i++){
            cin>>a[i];
            if(a[i]%2==0){//even
                even++;
            }else{
                odd++;
            }
        }
        if(even>odd){
            cout<<"NO"<<endl;
        }else{
            cout<<"YES"<<endl;
        }

    }
    return 0;
}

問題 E: Shortest Distance (20)

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

輸入

Each input file contains one test case. For each case, the first line contains an integer N (in [3, 105]), followed by N integer distances D1 D2 ... DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (<=104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 107.

輸出

For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.

樣例輸入

5 1 2 4 14 9
3
1 3
2 5
4 1

樣例輸出

3
10
7

程式碼:

#include <iostream>
#include<cstring>
using namespace std;
int D[100010];

int sum(int s,int e){
    int Sum=0;
    for(int i=s;i<e;i++){
        Sum+=D[i];
    }
    return Sum;
}

int main()
{
    int N,M;
    while(cin>>N){
        memset(D,0,sizeof(D));
        for(int i=1;i<=N;i++){
            cin>>D[i];
        }
        cin>>M;
        int a=0,b=0;
        int all=sum(1,N+1);//總路徑長度
        int s1,s2;
        while(M--){
            cin>>a>>b;
            if(a>b){int t=a;a=b;b=t;}
            s1=sum(a,b);
            s2=all-s1;//走另一條路
            cout<<(s1<s2?s1:s2)<<endl;
        }


    }
    return 0;
}

問題 F: A+B和C (15)

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

給定區間[-231, 231]內的3個整數A、B和C,請判斷A+B是否大於C。

輸入

輸入第1行給出正整數T(<=10),是測試用例的個數。隨後給出T組測試用例,每組佔一行,順序給出A、B和C。整數間以空格分隔。

輸出

對每組測試用例,在一行中輸出“Case #X: true”如果A+B>C,否則輸出“Case #X: false”,其中X是測試用例的編號(從1開始)。

樣例輸入

4
1 2 3
2 3 4
2147483647 0 2147483646
0 -2147483648 -2147483647

樣例輸出

Case #1: false
Case #2: true
Case #3: true
Case #4: false

程式碼:

#include <iostream>

using namespace std;
typedef long long ll;

int main()
{
    ll A,B,C;
    int count=1;
    short T;
    while(cin>>T){
        while(T--){
            cin>>A>>B>>C;
            if(A+B>C){
                cout<<"Case #"<<(count++)<<": true\n";
            }else{
                cout<<"Case #"<<(count++)<<": false\n";
            }
        }

    }

    return 0;
}

問題 G: 數字分類 (20)

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

給定一系列正整數,請按要求對數字進行分類,並輸出以下5個數字:

  • A1 = 能被5整除的數字中所有偶數的和;
  • A2 = 將被5除後餘1的數字按給出順序進行交錯求和,即計算n1-n2+n3-n4...;
  • A3 = 被5除後餘2的數字的個數;
  • A4 = 被5除後餘3的數字的平均數,精確到小數點後1位;
  • A5 = 被5除後餘4的數字中最大數字。

輸入

每個輸入包含1個測試用例。每個測試用例先給出一個不超過1000的正整數N,隨後給出N個不超過1000的待分類的正整數。數字間以空格分隔。

輸出

對給定的N個正整數,按題目要求計算A1~A5並在一行中順序輸出。數字間以空格分隔,但行末不得有多餘空格。

若其中某一類數字不存在,則在相應位置輸出“N”。

樣例輸入

13 1 2 3 4 5 6 7 8 9 10 20 16 18
8 1 2 4 5 6 7 9 16

樣例輸出

30 11 2 9.7 9
N 11 2 N 9

寫此題時心情極度不爽,程式碼極其渣,哪天無聊再重寫吧...

程式碼:

#include <iostream>
#include<string>
using namespace std;
int N;
int a[1010];
int C=0;

string A1(){
    int ans=0;
    for(int i=0;i<N;i++){
        if(a[i]%5==0&&a[i]%2==0){
            ans+=a[i];
        }
    }
   if(ans==0) return "N";
    char str[1010];
    sprintf(str,"%d",ans);
    string ss=str;
    return ss;
}

string A2(){
    int ans=0;
    int sign=1;
    int flag=0;
    for(int i=0;i<N;i++){
        if(a[i]%5==1){
            ans+=(a[i]*sign);
            sign*=-1;
            flag=1;
        }
    }

    if(flag==0) return "N";
    char str[1010];
    sprintf(str,"%d",ans);
    string ss=str;
    return ss;
}

string A3(){
    int ans=0;
    for(int i=0;i<N;i++){
        if(a[i]%5==2){
            ans++;
        }
    }

    if(ans==0) return "N";
    char str[1010];
    sprintf(str,"%d",ans);
    string ss=str;
    return ss;
}

int A4(){
    int ans=0;
    for(int i=0;i<N;i++){
        if(a[i]%5==3){
            ans+=a[i];
            C++;
        }
    }
    return ans;
}

string A5(){
    int ans=0;
    for(int i=0;i<N;i++){
        if(a[i]%5==4){
            if(ans<a[i])
                ans=a[i];
        }
    }
    if(ans==0) return "N";
    char str[1010];
    sprintf(str,"%d",ans);
    string ss=str;
    return ss;
}

int main()
{
    cin>>N;
    for(int i=0;i<N;i++){
        cin>>a[i];
    }
    cout<<A1()<<" "<<A2()<<" "<<A3()<<" ";
    int sum=A4();
    if(sum==0){
        cout<<"N";
    }else{
        printf("%.1f",sum*1.0/C);
    }
    cout<<" "<<A5();
    return 0;
}

問題 H: 部分A+B (15)

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

正整數A的“DA(為1位整數)部分”定義為由A中所有DA組成的新整數PA。例如:給定A = 3862767,DA = 6,則A的“6部分”PA是66,因為A中有2個6。

現給定A、DA、B、DB,請編寫程式計算PA + PB。

輸入

輸入在一行中依次給出A、DA、B、DB,中間以空格分隔,其中0 < A, B < 1010。

輸出

在一行中輸出PA + PB的值。

樣例輸入

3862767 6 13530293 3
3862767 1 13530293 8

樣例輸出

399
0

程式碼:

#include<iostream>
#include<string>
using namespace std;
typedef long long ll;

ll countP(string s,char a){
	int x=a-'0';
	ll ans=0;
	for(int i=0;i<s.length();i++){
		if(s[i]==a){
			ans=ans*10+x;
		}
	}
	return ans;
}


int main()
{
	string A,B;
	char DA,DB;
	ll pa=0,pb=0;
	while(cin>>A>>DA>>B>>DB){
		pa=countP(A,DA);
		pb=countP(B,DB);
		cout<<pa+pb<<endl;
	}
	return 0;
}

問題 I: 錘子剪刀布 (20)

時間限制: 1 Sec  記憶體限制: 32 MB

題目描述

大家應該都會玩“錘子剪刀布”的遊戲:兩人同時給出手勢,勝負規則如圖所示:

現給出兩人的交鋒記錄,請統計雙方的勝、平、負次數,並且給出雙方分別出什麼手勢的勝算最大。

輸入

輸入第1行給出正整數N(<=105),即雙方交鋒的次數。隨後N行,每行給出一次交鋒的資訊,即甲、乙雙方同時給出的的手勢。C代表“錘子”、J代表“剪刀”、B代表“布”,第1個字母代表甲方,第2個代表乙方,中間有1個空格。

輸出

輸出第1、2行分別給出甲、乙的勝、平、負次數,數字間以1個空格分隔。第3行給出兩個字母,分別代表甲、乙獲勝次數最多的手勢,中間有1個空格。如果解不唯一,則輸出按字母序最小的解。

樣例輸入

10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J

樣例輸出

5 3 2
2 3 5
B B
#include<iostream>
using namespace std;
int win1,pin1,fail1;
int win2,pin2,fail2;
int c1,c2,j1,j2,b1,b2;//記錄甲乙分別CJB勝的次數
char p1,p2;//甲乙出的是

int judge(){
	if(p1=='C'){
		switch(p2)
		{
			case 'C':
				return 0;//平
			case 'J':
				return 1;//p1勝
			case 'B':
				return 2;//p2勝
		}
	}

	if(p1=='J'){
		switch(p2)
		{
			case 'J':
				return 0;//平
			case 'B':
				return 1;//p1勝
			case 'C':
				return 2;//p2勝
		}
	}

	if(p1=='B'){
		switch(p2)
		{
			case 'B':
				return 0;//平
			case 'C':
				return 1;//p1勝
			case 'J':
				return 2;//p2勝
		}
	}

}

//勝率最高
char most1(){
	if(b1>=c1&&b1>=j1){
		return 'B';
	}
	if(c1>=b1&&c1>=j1){
		return 'C';
	}
	if(j1>=c1&&j1>=b1){
		return 'J';
	}

}

char most2(){
	if(b2>=c2&&b2>=j2){
		return 'B';
	}
	if(c2>=b2&&c2>=j2){
		return 'C';
	}
	if(j2>=c2&&j2>=b2){
		return 'J';
	}

}

int main(){

	int T;
	
	while(cin>>T){
		win1=pin1=fail1=win2=pin2=fail2=0;
		c1=c2=j1=j2=b1=b2=0;

		while(T--){
			cin>>p1>>p2;
			if(judge()==0){
				pin1++;
				pin2++;
			}else if(judge()==1){//p1勝
				if(p1=='C'){
					c1++;
				}else if(p1=='J'){
					j1++;
				}else{
					b1++;
				}
				win1++;
				fail2++;

			}else{//p2勝
				if(p2=='C'){
					c2++;
				}else if(p2=='J'){
					j2++;
				}else{
					b2++;
				}
				win2++;
				fail1++;
			}
		}
		cout<<win1<<" "<<pin1<<" "<<fail1<<endl;
		cout<<win2<<" "<<pin2<<" "<<fail2<<endl;
		cout<<most1()<<" "<<most2()<<endl;		

	}
	return 0;
}