刘汝佳第三章习题

3-1 得分 (UVa 1585)

题目:有一个客观的测试结果,如“OOXXOXXOOO”,一个“O”表示一个问题的正确答案,一个“X”表示一个错误的答案。这个测试的每个问题的分数是由它自己计算的,例如,第10个问题的得分是3,它是由它自己和它的前两个连续的O得到的。
因此,“OOXXOXXOOO”的分数是由“1 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 2 + 3”计算得到的10。
你要编写一个计算测试结果分数的程序。

提示:用一个flag标记是否是O开头

#include <iostream>
using namespace std;

int main(void)
{
    string str;
    cin >> str;
    int len = str.length();
    bool start = false;
    int count = 0;
    int sum = 0;
    for (int i = 0; i < len; i++){
        if (str[i] == 'O'){
            start = true;
            count++;
        } else if (str[i] == 'X') {
            start = false;
            count = 0;
        }
        if (start) {
            sum += count;
        }
    }
}

3-2分子量 (UVa 1586)

题目大意:给出一种物质的分子式(不带括号),求分子量。本题中分子式只包含4种原子,分别为C、H、O、N,

原子量分别为12.01,1.008,16.00,14.01

提示:用数组保存四种原子的分子量,用flag标记当前位是字母还是数字。如果是数字,超过一位的,把每一位的数值从字符串中提取出来。用数组保存每一位的分子量。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
float ans[100];
float mass[] = {12.01, 1.008, 16.00, 14.01};
char str[10];
int len;
int num(int pos, int len)//pos为数字开始的位置,len为分子式长度
{
    int temp;
    for (int i=pos;i<len;i++){ //获取数字长度,并存储到temp
        if(isdigit(str[i])){
            temp=i;
        } else {
            break;
        }
    }

    int n = 0;
    for (int i=pos; i <=temp;i++){ //根据每一十进制位计算分子量
        n = n * 10 +  (str[i] - '0');
    }
    return n - 1; //注意减一是因为最后计算的时候,字母本身占一倍 
  
}

int main(void)
{
    int flag = 0; 
    scanf("%s", str);
    len = strlen(str);
    for (int i = 0; i < len; i++){
        if (str[i] == 'C'){
            ans[i]=mass[0];
        }
        if (str[i] == 'H'){
            ans[i]=mass[1];
        }
        if (str[i] == 'O'){
            ans[i]=mass[2];
        }
        if (str[i] == 'N'){
            ans[i]=mass[3];
        }
        if(isdigit(str[i])&&flag==0){ //初始状态flag = 0,直接进入if判断 
            ans[i]=ans[i-1] * num (i, len); //若该位为数字,则计算数字乘以前面元素的分子量
            flag = 1; //做标记,表示计算数字,下次循环忽略此if判断
        } 
        if (isalpha(str[i])){ //若该位为字母,则标记flag = 0复位,方便下次循环进入上面if判断
            flag = 0;
        }
    }
    
    float sum = 0;
    for (int i = 0; i<len;i++){
       sum+=ans[i];
    }
    printf("%.3f\n",sum);
    return 0;
}

3-3 数数字(UVa1225)

题意:
把前n(n<=10000)个整数顺次写在一起,如n=15时,123456789101112131415
计算0-9各出现了多少次(输出10个数,分别是数字0-9出现的次数)
#include <iostream>
using namespace std;

int main(void)
{
    int sum[10] = {}; //sum[i]表示数字i的个数
    for (int i = 1; i <= 10000; i++){
        int j = i;
        while (j > 0){
            int k;
            k = j % 10; //获取个位
            sum[k]++;   //个位数字的个数加一
            j /= 10;    //下一位
        }
    }

    for  (int i = 0; i < 10; i++){
        cout << i <<  "  : "  << sum[i] << endl;
    }
}

3-4周期串(UVa455)

题目:求一个串的最小循环节。

解题思路:

对一个字符串求其最小周期长度,那么,最小周期长度必定是字符串长度的约数,即最小周期长度必定能被字符串长度整除

其次,对于最小周期字符串,每位都能对应其后周期字串的每一位,

 

if(a[j]!=a[j%3])说明不对应,不是周期,进行下一位扫描。

#include  <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

using namespace std;

char str[104];

int main(void)
{
    int n;
    while (~scanf("%d",&n))
        while (n--){
            scanf("%s", str);
            int len = strlen(str);
            for(int k, i = 1; i < len; i++){
                if (len % i == 0 ) //若子串长度能够整除母串
                    for (k = i; k < len; k++) //开始匹配
                        if (str[i] != str[k%i]) //如果不能匹配
                            break; //则跳出
                if (len == i) {//若全部匹配 
                    cout << i;
                    break;
                }
            }
            if (n) cout << endl;
    }
}

3-8 循环小数(UVa202)

大致题意
输入整数a(0<=a<=3000)和 b (1<=b<=3000),输出a/b的循环小数表示以及循环字节长度。例如a=5,b=43,小数表示为0.(116279069767441860465),循环字节长度为21

#include<stdio.h>  
#include<cstring>  
#include<algorithm>  
#include <iostream>
#define HardBoy main()  
#define ForMyLove return 0;  
using namespace std;  
const int MYDD = 1103+1e4;  
  
int HardBoy {  
    int quotient[MYDD];  
    int remainder[MYDD];  
    int u[MYDD];  
    int n, m, t;  
      
    while(scanf("%d %d", &n, &m) != EOF) {  
        t = n;/*3000以内*/  
        memset(quotient, 0, sizeof(quotient));  
        memset(u, 0, sizeof(u));  
        int cnt = 0;  
        quotient[cnt++] = n/m;  
        n %= m;
        //n为余数,循环前数组u[]被置0,!u[n]为真,进入循环
        while(!u[n] && n) { //u[n] == 0 

            //debug:cout << "before n= " << n << endl;
            u[n] = cnt;
            //一开始数组u[n] = cnt == 0,!u[n]为真,持续循环
            //之后cnt > 0,每次循环,u[n]被赋正值
            //直到循环至n重复出现,即出现循环节,这时u[n]已经被赋值为正值,!u[n]为假,跳出循环
            //debug:cout << "u[n]= " << cnt <<endl;
            remainder[cnt] = n;  //记录余数
            //debug:cout << "reamainder= " << n << endl;
            quotient[cnt++] = 10*n/m;  //记录商
            //debug:cout << "quotient= " << 10*n/m << endl;
            n = 10*n%m;  
            //debug:cout << "after n= " << n << endl;

            //debug:cout << endl; 
        }  
  
        printf("%d/%d = %d.", t, m, quotient[0]);  
        for (int i = 1 ; i < cnt && i <= 50 ; i++) {  
            if (n && remainder[i] == n) printf("(");  
            /*存在循环节->开始存在余数相同的位置*/  
            printf("%d",quotient[i]);  
        }  
        if (!n) printf("(0");
        //余数为零
        if (cnt > 50) printf("...");  
        printf(")\n");  
        printf("   %d = number of digits in repeating cycle\n\n",!n? 1:cnt-u[n]);  
  
    }  
    ForMyLove  
}

3-9 子序列(UVa 10340)

题意:给两个字符串A 和 B。 如果在B中能找到非连续字串和A匹配输出 YES 不能输出NO。
思路B一个个字母遍历过去每对应上A的一个字母就找A的下一个字母直到结束。。

#include <stdio.h>  
#include <string.h>  
  
char a[100005], b[100005];  
int main() {  
    while (~scanf("%s%s", a, b)) {  
        int star = 0, lenb = strlen(b), lena = strlen(a);  
        for (int i = 0; i < lenb; i ++) {  
            if (a[star] == b[i])  
                star ++;  
            if (star == lena) {  
                printf("Yes\n");  
                break;  
            }  
        }  
        if (star != lena)  
            printf("No\n");  
    }  
    return 0;  
}

 

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注