OJ 系列之常规练习题(二)

1、坐标移动

/*
开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。
从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。

输入:
合法坐标为A(或者D或者W或者S) + 数字(两位以内)
坐标之间以;分隔。

非法坐标点需要进行丢弃。如AA10;  A1A;  $%$;  YAD; 等。

下面是一个简单的例子 如:

A10;S20;W10;D30;X;A1A;B10A11;;A10;

处理过程:

起点(0,0)
+ A10 = (-10,0)
+ S20 = (-10,-20)
+ W10 = (-10,-10)
+ D30 = (20,-10)
+ x = 无效
+ A1A = 无效
+ B10A11 = 无效
+ 一个空 不影响
+ A10 = (10,-10)

结果 (10, -10)

输入:  
一行字符串   
输出:  
最终坐标,以,分隔

样例输入: A10;S20;W10;D30;X;A1A;B10A11;;A10;

样例输出: 10,-10

*/

【解题思路】先取出正常坐标点,分别存在4个数组中,然后对这4个数组进行坐标运算。

代码实现

#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;

int CalCoordinate(char inputStr[])
{
    if(!inputStr)
        return 0;

    int i = 0;
    int inputStrLen = strlen(inputStr);
    int flag = 1;/*0为初始值,1为正常,2异常 用于舍弃非法字符*/
    int temp = 0;

    vector<int>Adata;
    vector<int>Ddata;
    vector<int>Wdata;
    vector<int>Sdata;

    /*1.得到正常坐标点,分别存在四个数组中*/
    while(inputStr[i]!='\0') {
        flag = 0;
        temp = 0;
        if(inputStr[i]=='A'){
            i++; /*判断后面字符是否为数值,直到';'作为一段指令的结束标志*/
            while(inputStr[i]!=';'&&inputStr[i]!='\0') {
                if(inputStr[i]>='0'&&inputStr[i]<='9') {
                    temp = temp*10+inputStr[i]-'0';
                    flag = 1;
                } else {
                    flag = 2; /*异常*/
                } //if
                i++;
            }//while
            if(flag==1) {
                Adata.push_back(temp);
            }
        } else if(inputStr[i]=='S') {
            i++;
            while(inputStr[i]!=';'&&inputStr[i]!='\0') {
                if(inputStr[i]>='0'&&inputStr[i]<='9') {
                    temp = temp*10+inputStr[i]-'0';
                    flag = 1;
                } else {
                    flag = 2;
                } //if
                i++;
            }//while
            if(flag==1) {
                Sdata.push_back(temp);
            }
        } else if(inputStr[i]=='W') {
            i++;
            while(inputStr[i]!=';'&&inputStr[i]!='\0') {
                if(inputStr[i]>='0'&&inputStr[i]<='9') {
                    temp = temp*10+inputStr[i]-'0';
                    flag = 1;
                } else {
                    flag = 2;
                } //if 
                i++;
            }//while
            if(flag==1) {
                Wdata.push_back(temp);
            }
        } else if(inputStr[i]=='D') {
            i ++;
            while(inputStr[i]!=';'&&inputStr[i]!='\0') {
                if(inputStr[i]>='0'&&inputStr[i]<='9') {
                    temp = temp*10+inputStr[i]-'0';
                    flag = 1;
                } else {
                    flag = 2;
                } //if 
                i++;
            }//while
            if(flag==1) {
                Ddata.push_back(temp);
            }
        } else {
            while(inputStr[i++]!=';'&&inputStr[i++]!='\0') {}
            flag = 2;
        }
    }
    /*2.分别计算四个数组中左右上下坐标*/
    int AdataLen = Adata.size();
    int DdataLen = Ddata.size();
    int WdataLen = Wdata.size();
    int SdataLen = Sdata.size();

    int SumX = 0;
    int SumY = 0;

    for(int i=0;i<AdataLen;i++) {
        SumX -= Adata[i];
    }
    for(int i=0;i<DdataLen;i++) {
        SumX += Ddata[i];
    }

    for(int i=0;i<WdataLen;i++) {
        SumY += Wdata[i];
    }
    for(int i=0;i<SdataLen;i++) {
        SumY -= Sdata[i];
    }

    printf("%d,%d\n",SumX,SumY);

    return 0;
}

int main()
{
#if 0
    char input[] = "A10;S20;W10;D30;X;A1A;B10A11;;A10;";
#else
    char input[1024];
    gets(input);
#endif
    CalCoordinate(input);
    //getchar();
    //getchar();
    return 0;
}

2、周期串问题

/*
功能:计算字符串的最小周期。
原型:
    int GetMinPeriod(char *string);
输入参数:
    char * string:字符串。
返回值:
    int 字符串最小周期。    
题目描述
如果一个字符串可以由某个长度为k的字符串重复多次得到,
我们说该串以k为周期。例如,abcabcabcabc以3为周期
(注意,它也可以612为周期,结果取最小周期3)。字符串的长度小于等于100,由调用者保证。
详细描述:
接口说明
原型:
    int GetMinPeriod(char *inputstring);
输入参数:
    char * inputstring:字符串
返回值:
    int 字符串最小周期
*/
int GetMinPeriod(char *inputstring)
{
    /*在这里实现功能*/
    if(!inputstring)
        return 0;
    int i = 0,j=0;
    int flag = 0;/*flag == 1找到*/
    int len = strlen(inputstring);//len为字符串长度
    for(i=1; i <= len; i++)
        //字符串的长度一定可以被周期整除
        if(len%i == 0) {
            flag = 1;
            //检测 字符串是否具有周期性
            //inputstring[i]为第二周期的第一个字符
            for(j=i; j<len; j++) {
                if(inputstring[j] != inputstring[j%i]) {
                    flag = 0;
                    break;
                }
        }
        if(flag)//找到周期跳出
            break;
    }

    return i;
}

3、矩阵相乘2

/*
功能: 矩阵相乘

输入: MatrixA,MatrixB

输出: MatrixC

返回: 0
样例输入:

{1, 2, 3}, {4, 5, 6}, {7, 8, 9}

{1, 2, 3}, {4, 5, 6}, {7, 8, 9}

样例输出:

{30, 36, 42}, {66, 81, 96}, {102, 126, 150}



*/

本题输入的是一个方阵求解,N*N的,那只需要位置对齐即可求解了。

nt matrix(int **MatrixA, int **MatrixB, int **MatrixC, int N)
{

    if(!*MatrixA||!*MatrixB||!*MatrixC||N<=0)
        return -1;
    if(!MatrixA||!MatrixB||!MatrixC)
        return -1;

    int a,b;
    /*行*/
     for(int i = 0;i < N;++i){
     /*列*/
       for(int j = 0;j < N;++j){
           *((int*)MatrixC + i * N + j) = 0;
           for(int k = 0;k < N;++k){
               a = *((int*)MatrixA + i * N + k);
               b = *((int*)MatrixB + k * N + j);
               *((int*)MatrixC + i * N + j) +=  a * b;
           }//for
       }//for
   }//for

    return 0;
}

4、最大公约数

使用辗转相除法。

#include<stdio.h> 
void main()   /* 辗转相除法求最大公约数 */     
{     
   int a=2, b=4, c;

   scanf("%d%d", &a, &b); 

   while(b!=0)  /* 余数不为0,继续相除,直到余数为0 */     
   { 
        c=a%b;
        a=b;  
        b=c;
   }    
   printf("%d\n", a);    

}    

5、整数相除

Char *pResult的空间由调用者提供,结果中最多保存十位整数,五位小数,
整数部分超出十位,返回失败;小数部分超出五位,四舍五入;
存储结果以字符串形式显示,整数和小数部分需加上小数点。如结果为2.05,
则输出的结果为”2.05”。

int IntegerDivision (unsigned int dividend,
                            unsigned int divisor, 
                        char *pResult)
{
    /*在这里完成代码*/
    // 返回-1的情况除数为0或者整数部分大于十位的时候unsigned int最大为多少?
    //int数据类型,在32位系统中(现在基本上int都是32位),范围-2147483648~+2147483647。
    //unsigned类型 的int 范围:0~4294967295 即 0~(2的32次方-1)

    /*1.异常情况处理*/
    if(divisor==0)
        return -1;

    unsigned int  temp=dividend%divisor;

    if(temp==0) {
        unsigned int num=dividend/divisor;
        if(num>999999999)
            return -1;

        sprintf(pResult,"%d",num);

        return 0;

    } else {

        double num=(double)dividend/(double)divisor;

        char result[20];
        /*2.小数保留5位,精度为小数点后五位的浮点数*/
        sprintf(result,"%.5f",num);
        string s=result;

        int pos=s.find_first_of('.');
        if(pos>=11)
            return -1;

        int len=s.size()-1,nzeropos=len;
        bool iszero=true;
        /*3.去除小数部分的零*/
        while(iszero) {
            if(result[nzeropos]=='0')
                nzeropos--;
            else 
                iszero=false;

        }
        int relpos=0;
        /*4.判断当前字符串中有没有小数部分*/
        nzeropos=(result[nzeropos]=='.')?(nzeropos-1):nzeropos;

        for(relpos = 0;relpos<=nzeropos;relpos++) {
            pResult[relpos]=result[relpos];
        }

        pResult[nzeropos+1]='\0';


    }

    return 0;
}

6、字符串加解密

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

//1、对输入的字符串进行加解密,并输出。
//
//2加密方法为:
//当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B;字母Z时则替换为a;
//当内容是数字时则把该数字加1,如0替换1,1替换2,9替换0;
//其他字符不做变化。
//
//3、解密方法为加密的逆过程。


int Encrypt (char password[], char result[])
{
    /* 代码在这里实现 */
    if(!password||!result)
        return 0;
    int passwordLen = strlen(password);
    int i = 0;
    for(i = 0;i<passwordLen;i++) {
         if (password[i]>='a' && password[i]<='z') {
            if(password[i] == 'z') {
                result[i]  = 'A';
            } else {
                result[i] = password[i] -'a' + 'A'+1;
            }
        } else if (password[i]>='A' && password[i]<='Z') {
            if (password[i]=='Z') {
                result[i] = 'a';
            } else {
                result[i] = password[i] -'A' + 'a'+1;
            }

        } else if (password[i]>='0' && password[i]<='9') {
            if(password[i] == '9') {
                result[i] = '0';
            } else {
                result[i] = password[i] + 1;
            }

        } else {
            result[i] = password[i];
        }

    }
    result[i] = '\0';
    return 0;
}

int unEncrypt (char result[], char password[])
{
    /* 代码在这里实现 */
    if(!password||!result)
        return 0;
    int resultLen = strlen(result);
    int i = 0;

    for(i = 0;i<resultLen;i++) {
         if (result[i]>='a' && result[i]<='z') {
            if(result[i] == 'a') {
                password[i]  = 'Z';
            } else {
                password[i] = result[i] -'a' + 'A'-1;
            }
        } else if (result[i]>='A' && result[i]<='Z') {
            if (result[i]=='A') {
                password[i] = 'z';
            } else {
                password[i] = result[i] -'A' + 'a'-1;
            }

        } else if (result[i]>='0' && result[i]<='9') {
            if(result[i] == '0') {
                password[i] = '9';
            } else {
                password[i] = result[i] - 1;
            }

        } else {
            password[i] = result[i];
        }

    }
    password[i] = '\0';

    return 0;
}

7、水仙花

#include <stdlib.h>
#include "oj.h"
// 功能:判断输入 nValue 是否为水仙花数
// 输入: nValue为正整数
// 输出:无
// 返回:如果输入为水仙花数,返回1,否则返回0
long long cal(int nValue,int CurNumberDigits)
{
    long long sum = 1;
    while(CurNumberDigits)
    {
        sum *= nValue;
        CurNumberDigits--;
    }
    return sum;
}
unsigned int IsDaffodilNum(unsigned int  nValue)
{   
    if(nValue<100)
        return 0;
    unsigned int curNum  = nValue;
    int a[10];
    int i = 0;
    int CurNumberDigits = 0;
    long long sum = 0;
    long long sumtemp = 0;
    while(curNum > 9) {
        a[i] = curNum%10; /*1.存储每一位数字*/
        i ++;
        curNum = curNum/10;
    }
    a[i] = curNum;
    CurNumberDigits = i+1;

    for(i = 0;i< CurNumberDigits;i++) {
        long long sumtemp = cal(a[i],CurNumberDigits);
        sum = sum + sumtemp;
    }

    if(sum == nValue) {
        return 1;
    }

    return 0;
}

8、阿姆斯特朗数


#include "OJ.h"

/* 功能: 求n(n ≤ 65536)以内的所有阿姆斯特朗数 原型: int CalcArmstrongNumber(int n); 输入参数: int n: n ≤ 65536 返回值: n以内的阿姆斯特朗数的数量。 */

int CalcArmstrongNumber(int n)
{
    /*在这里实现功能*/
    if (n <= 0) 
        return 0;

    int a[10];

    int CurNumberDigits = 0;
    int i = 0;
    int j = 0;
    int sum,curNum = 0;
    int numCount = 0;

    for(j=2;j<n;j++) {
        curNum = j;

        while(curNum > 9) {
            a[i] = curNum%10; /*1.存储每一位数字*/
            i ++;
            curNum = curNum/10;
        }
        a[i] = curNum;
        CurNumberDigits = i+1;

        for(i = 0;i< CurNumberDigits;i++) {
            sum += a[i]*a[i]*a[i];
        }


        if(sum == j) {
            numCount ++; /*计数加1*/       
        }
        i = 0;
        sum = 0;
        CurNumberDigits = 0;
    }

    return numCount;
}

9、大数相乘


#include "oj.h"
using namespace std;



/***************************************************************************** Prototype : multiply Description : 两个任意长度的长整数相乘, 输出结果 Input Param : const std::string strMultiplierA 乘数A const std::string strMultiplierB 乘数B Output : std::string strRst 乘法结果 Return Value : int 0 正确 -1 异常 *****************************************************************************/
int multiply (const std::string strMultiplierA,
                  const std::string strMultiplierB, 
                  std::string &strRst) 
{

    /* 在这里实现功能 */
    if(strMultiplierA.length()==0 ||\
        strMultiplierB.length()==0)
        return -1;
    int maxlen = int(strMultiplierA.length()+strMultiplierB.length());
    int minlen = int(strMultiplierA.length()>strMultiplierB.length()?\
                   strMultiplierB.length():strMultiplierA.length());
    unsigned int *a   = new unsigned int[minlen*maxlen];
    unsigned int *end = new unsigned int[maxlen];

    for(int i=0;i<minlen*maxlen;i++)
        a[i]=0;
    for(int i=0;i<maxlen;i++)
        end[i]=0;


    if(strMultiplierA.length()>strMultiplierB.length()) {
        int add=0;
        for(int i=0;i<minlen;i++) {
            for(int j=0;j<maxlen-minlen;j++) {
                /*从字符串最高位(数字最低位)相乘*/
                a[i*maxlen+j+add]=(strMultiplierB[minlen-i-1]-'0')* \
                                  (strMultiplierA[maxlen-minlen-j-1]-'0');
            }
            add++;
        }
    } else {    
        int add=0;
        for(int i=0;i<minlen;i++) {
            for(int j=0;j<maxlen-minlen;j++) {
                a[i*(maxlen)+j+add]=(strMultiplierA[minlen-i-1]-'0')*\
                                (strMultiplierB[maxlen-minlen-j-1]-'0');
            }
            add=add+1;
        }

    }


    for(int i=0;i<maxlen;i++) {
        for(int t=0;t<minlen;t++) {
           end[i]+=a[t*(maxlen)+i];
        }
    }

    for(int i=0;i<maxlen-1;i++) {
        if(end[i]>=10) {
            end[i+1]=end[i+1]+end[i]/10;
            end[i]=end[i]%10;
        }
    }


  //数组转换到字符串里面去
    int weizhi=0;
    for(int i=maxlen-1;i>=0;i--) { 
        if(end[i]!=0) {
            weizhi=i;
            break;
        }  
    }
    char app=end[weizhi]+'0';
    strRst.push_back(app);

    for(int j=weizhi-1;j>=0;j--) {   
        char app=end[j]+'0';
        strRst.push_back(app);

    }

    return 0;
}

int multiply (char strMultiplierA[],char strMultiplierB[], char strRst[])
{
    if(!strMultiplierA||!strMultiplierB||!strRst)
        return -1;

    int lenA = strlen(strMultiplierA);
    int lenB = strlen(strMultiplierB);


}

10、整数分隔

一个整数总可以拆分为2的幂的和,例如:

7=1+2+4
7=1+2+2+2
7=1+1+1+4
7=1+1+1+2+2
7=1+1+1+1+1+2
7=1+1+1+1+1+1+1

总共有六种不同的拆分方式。

再比如:4可以拆分成:
4 = 4,
4 = 1 + 1 + 1 + 1,
4 = 2 + 2,
4=1+1+2。

用f(n)表示n的不同拆分的种数,例如f(7)=6.

要求编写程序,读入n(不超过1000000),输出f(n)%1000000000。
输入:  
每组输入包括一个整数:N(1<=N<=1000000)。
输出:  
对于每组数据,输出f(n)%1000000000。
输出有多行,每行一个结果。
输入数据如果超出范围,输出-1。

解题思路:
这题目是找规律的。多试几组数据就可以得到
当n=2k+1为奇数时,f(2k+1)=f(2k)。
其实2k+1的拆分第一项肯定为1,若去掉这个1,就和2k的拆分一样了。

当n=2k为偶数时,我们考虑有1和没有1的拆分。
若有1,则前2项均为1,就和2k-2的拆分一样了。
若没有1,则将每项除以2,就和k的拆分一样了。
故有f(2k)=f(2k-2)+f(k);

代码实现

#include <iostream> 
using namespace std;  

int search[1000002]={0};

int main()  
{  
    unsigned int maxnum = 1000000;   

    int input = 0, i;  
    search[0] = 1, search[1] = 1;  
    for(i=1; i<=500000; i++) {  
        search[2*i] = (search[2*i - 2] + search[i])%1000000000;  
        search[2*i + 1] = search[2*i];  
    }  

    int num = -1;

    while(scanf("%d",&input)!=EOF) {  
        if((input>=1)&&(input<=1000000)) {  
            printf("%d\n",search[input]);
        }  
        else {  
            printf("%d\n",num); 
        }   
    }  

    return 0;  
}

你可能感兴趣的:(字符串操作,大数相乘,OJ,矩阵运算)