编程练习八

  1. 电灯问题
    一条长廊里依次装有n(1 ≤ n ≤ 65535)盏电灯,从头到尾编号1、2、3、…n-1、n。每盏电灯由一个拉线开关控制。开始,电灯全部关着。有n个学生从长廊穿过。第一个学生把号码凡是1的倍数的电灯的开关拉一下;接着第二个学生把号码凡是2的倍数的电灯的开关拉一下;接着第三个学生把号码凡是3的倍数的电灯的开关拉一下;如此继续下去,最后第n个学生把号码凡是n的倍数的电灯的开关拉一下。n个学生按此规定走完后,长廊里电灯有几盏亮着。
    注:电灯数和学生数一致。

方法一:简单的双循环方法,耗时

#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;

#define MAX 65535


int main( )
{
    int i,light_num,countnum,j=1, left_num =0;
    printf("please input the number of the lights:\n");
    scanf("%d",&light_num);
    int a[MAX] = {0};
    while (j <= light_num)
    {
        countnum = 0;
        for (i = 1; i <= light_num; i++ )
        {
            if (j % i == 0) countnum++;
        }
        if (countnum % 2 != 0) left_num++; // 基数的灯还是亮着的
        j++;
    }
    printf("%d",left_num);
    return 0;

}

方法二:本题目可以转化为:求不大于N的完全平方数的个数。
对于任何一盏灯,由于它原来不亮,那么当它的开关被按奇数次时,灯是开着的;当它的开关被按偶数次时,灯是关着的;一盏灯的开关被按的次数,恰等于这盏灯的编号的因数的个数;要求哪些灯还亮着,就是问哪些灯的编号的因数有奇数个.显然完全平方数有奇数个因数。每个数除以一个数A等于另一个数B,那么A和B都是它的因数,于是因数是成对出现的,但是要因数是奇数,就必须A=B所以这个数就必须是一个是的平方得到的。

for(int i = 1; i < N; i++)
    {
        if(i*i > N)
            break;
        left_num++;
    }
  1. 相同子串
    输入一个字符串,判断是否含有相同的子串(字串长度大于1),是,输出1,否,输出0。
    例如12312含有两个12,所以输出1;23456则没有相同子序列,输出0.

输入:12312
输出:1

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string s;
    cout<<"输入一串数字\n";
    cin>>s;
    bool l = false;
    for(int i = 0; i < s.size()-1; i++)
    {
        for(int j = i+1; j < s.size()-1; j++)
        {
            if(s[i]==s[j] &&s[i+1] == s[j+1])
            {
                l =true;
                break;
            }
        }
    }
    if(l) cout<<"1\n";
    else cout <<"0\n";

    system("pause");
    return 0;
}

3.. 两个整数相除,将结果用字符串返回。如果是循环小数,将循环的位用括号括起来。
函数原型为 void div(const int a,const int b,char *str)

输入:1 3
输出:0.(3)

#include<iostream>
#include<string>
using namespace std;
const int maxn = 100; //设置字符串的最大位数
const int max_INT = 10000; 
int reminder_exist[max_INT];
int reminder_pos[max_INT];

void div(const int a, const int b, char *str)
{
    int numerator,denominator,quotient, reminder, outcnt = 0;
    int flag = 0; //负数标志
    int original_numerator = a; //求整数部分用到的分子
    memset(reminder_exist, 0, sizeof(reminder_exist));
    memset(reminder_pos, 0, sizeof(reminder_pos));
    numerator = a; //由于定义const int所以我们要改变分子分母时候,所以我们通过中间变量转化
    denominator = b;

    if(a*b < 0)
        flag = 1;

    //将分子和分母变成整数
    numerator = numerator < 0 ? -numerator:numerator; 
    denominator = denominator < 0 ? -denominator:denominator;

    quotient = numerator/denominator;
    reminder = numerator%denominator;   
    int integer = quotient;

    //找出循环
    //int found_cycle = 0; 
    int cycle_pos = maxn; //循环的位置
    int cycle_len = 0; //初始化循环长度
    int i = 0;
    for(i = 0; i <= maxn; i++)
    {
        //找出余数相等的情况,求出循环周期
        if(reminder_exist[reminder])
        {
            cycle_pos = reminder_pos[reminder];
            cycle_len = i - cycle_pos;
            break;
        }
        else
        {
            reminder_exist[reminder] = 1;
            reminder_pos[reminder] = i;
        }

        numerator = reminder *10;
        quotient = numerator/denominator;
        reminder = numerator%denominator; 

        str[outcnt++] = quotient + '0'; //将更新的商存入字符串中
    }
    str[outcnt++] = '\0';

    if(!flag)
    {
        cout << integer << "." ;
    }
    else
        cout << "-" << integer << ".";

    for(int j = 0; j < cycle_pos; j++)
        cout << str[j];

    cout << "(";

    for(int j = cycle_pos; j < i;j++)
        cout <<  str[j];
    cout << ")" << endl;
}


int main()
{
    int a,b,flag = 0;
    char s[maxn];
    cin >> a >> b;
    if(!a && !b)
        return 0;
    div( a, b,s);

    system("pause");
    return 0;
}

4.. 地铁换乘问题

已知2条地铁线路,其中A为环线,B为东西向线路,线路都是双向的。经过的站点名分别如下,两条线交叉的换乘点用T1、T2表示。编写程序,任意输入两个站点名称,输出乘坐地铁最少需要经过的车站数量(含输入的起点和终点,换乘站点只计算一次)。

地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 A16 A17 A18

地铁线B(直线)经过车站:B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B10 T2 B11 B12 B13 B14 B15

输入:输入两个不同的站名

输出:输出最少经过的站数,含输入的起点和终点,换乘站点只计算一次

输入样例:A1 A3

输出样例:3

思路:分三种情况讨论:1)两个站点都在A线上,2)两个站点都在B线上,3)两个站点在不同的线上,需要换乘。这里简单的使用数字代表站点:1~18:A1~A18,19:T1,20:T2,21~35:B1~B15. 且假设如果在不同线上的话,B线站为终点站。

实验代码:

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

#define LINENUM 35

int main()
{
    //int linestop[LINENUM]; // 1~18 为A线站点, 19:T1, 20:T2, 21~35 为B线站点
    int stop1 = 0, stop2 = 0, temp, shortline = 0;


    printf("please input the two stop in number: here 1~18 for A1 ~ A18, 19:T1, 20:T2, 21~35 for B1 ~ b15, and stop1 < stop2.\n");
    scanf("%d%d", &stop1, &stop2);

    //如果站点都在A线
    if ( stop1 >= 1 && stop1 <= 20  && stop2 >=1 && stop2 <=20)
    {
        temp = ( stop2 - stop1 + 1) < (20 - (stop2 - stop1) + 1) ? (abs(stop1 - stop2) + 1) :( 20 - abs(stop1 - stop2) + 1);
        shortline = temp;
    }

    // 如果站点都在B线
   if (stop1 >= 19 && stop1 <= 35 && stop2 >= 19 && stop2 <= 35)
    {
        if (stop1 == 19)
        {
            if( stop2 >= 26 && stop2 <= 30)
                shortline = stop2 - stop1 - 5;
            else if (stop2 >30 )
                shortline = stop2 - stop1 -5 ;
            else
                shortline =  stop2 - stop1 + 1;
        }

        if (stop1 == 20)
        {
            if( stop2 >= 26 && stop2 <= 30)
                shortline = stop2 - stop1 + 1;
            else if (stop2 >30 )
                shortline = stop2 - stop1 + 2;
            else if (stop2 = 19)
                shortline =  1 + 4 + 1;
            else
                shortline = stop2 - 19 + 6;
        }
         if (stop1 <= 25)
        {
            if( stop2 >= 26 && stop2 <= 30)
                shortline = stop2 - stop1 + 1 + 1;
            else if (stop2 >30 )
                shortline = stop2 - stop1 + 2;
            else if (stop2 = 20)
                shortline = 5 + 1 + 4 + 1;
            else
                shortline = stop2 - stop1 + 1;
        }
        if (stop1 < 31)
        {
            if( stop2 >= 26 && stop2 <= 30)
                shortline = stop2 - stop1 + 1 ;
            else if (stop2 >30 )
                shortline = stop2 - stop1 + 2;
            else
                shortline = 5 + 1 ;
        }
        if (stop1 >= 31)
        {
            shortline = stop2 - stop1 + 1;
        }
    }

    //如果站点在A、B线上
    if ( stop1 < 10 )
    {
        if ( stop2 > 20 && stop2 < 26)
            shortline = 9 - stop1 + 1 + 26-stop2;
        if ( stop2 >= 26 && stop2 <= 30)
            shortline = (9 - stop1 + 1 + 1 + stop2 - 26 + 1) < (stop1 - 1 + 1 + 6 + 31 - stop2) ? (9 - stop1 + 1 + 1 + stop2 - 26 + 1) : (stop1 - 1 + 1 + 6 + 31 - stop2);
        if (stop2 >= 31)
            shortline = (9 - stop1 + 1 + 7 + stop2 - 31 + 1) < (stop1 - 1 + 1 + 6 + stop2 - 31 + 1)? (9 - stop1 + 1 + 7 + stop2 - 31 + 1) : (stop1 - 1 + 1 + 6 + stop2 - 31 + 1);

    }
    if (stop1 >= 10 && stop1 <= 13)
    {
        if ( stop2 > 20 && stop2 < 26)
            shortline = stop1 - 10 + 1 + 26 - stop2;
        if ( stop2 >= 26 && stop2 <= 30)
            shortline = (stop1 -10 + 1 + stop2 - 26 + 1) < (13 - stop1 + 1 + 31 - stop2) ? (stop1 -10 + 1 + stop2 - 26 + 1): (13 - stop1 + 1 + 31 - stop2);
        if (stop2 >= 31)
            shortline =  13 - stop1 + 1 + 1+ stop2 - 31 + 1;
    }
    if (stop1 > 13 && stop1 <= 18)
    {
        if ( stop2 > 20 && stop2 < 26)
            shortline = ( stop1 - 14 + 1 + 10 + 26 - stop2) < ( 19 - stop1 + 1 + 7 + 26 - stop2) ? ( stop1 - 14 +1 + 10 + 26 - stop2) : ( 19 - stop1 + 1 + 7 + 26 - stop2);
        if ( stop2 >= 26 && stop2 <= 30)
            shortline = (stop1 -14 + 1 + 10 + stop2 - 26 + 1) < (19 - stop1 + 1 + 1 + 31 - stop2) ? (stop1 -14 + 1 + 10 + stop2 - 26 + 1): (19 - stop1 + 1 + 1 + 31 - stop2);
        if (stop2 >= 31)
            shortline =  19 - stop1 + 1  + 1 + stop2 - 31 + 1;
    }
    printf("%d\n", shortline);

    system("pause");

    return 0 ;
}

这里写图片描述

后来百度了一下,这到题还有这样的一个思路:http://www.2cto.com/kf/201309/247411.html

另外还有类似的:http://www.bkjia.com/ASPjc/744512.html

这里刚开始调试程序的时候出现了scanf问题:
如果是scanf(“%d,%d,%d”,&a,&b,&c);用非格式符“ , ”作间隔符,故输入时应为:5,6,7

如果是scanf(“%d %d %d”,&a,&b,&c);,其中没有“,”分隔符,则输入不需要用逗号隔开,使用空格就行:5 6 7

参阅:http://blog.csdn.net/to_xidianhph_youth/article/details/37592527

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值