刷题的一天

1、有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。

输入描述:

输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,分别给出a1,a2……an的值。

输出描述:

输出不同的选择物品的方式的数目。

输入:3 20 20 20

输出:3

该题可以利用递归,构建状态转移公式来计算,代码如下:

#include<iostream>
using namespace std;
int n=1,a[100];
int count(int i,int sum){
    if(sum==0) return 1;
    if(i==n || sum<0) return 0;
    return count(i+1,sum-a[i])+count(i+1,sum);
}
int main(){
    while(cin>>n){
        for(int i =0;i<n;i++){
            cin>>a[i];
        }
        cout<<count(0,40)<<endl;
    }
    return 0;
    
}

在外部定义函数count来计算组合数量,时间复杂度上大约为n,但空间复杂度似乎为n。和递归的性质一样,都是拿时间换空间。

2、The digital root of a positive integer is found by summing the digits of the integer. If the resulting value is a single digit then that digit is the digital root. If the resulting value contains two or more digits, those digits are summed and the process is repeated. This is continued as long as necessary to obtain a single digit.     For example, consider the positive integer 24. Adding the 2 and the 4 yields a value of 6. Since 6 is a single digit, 6 is the digital root of 24. Now consider the positive integer 39. Adding the 3 and the 9 yields 12. Since 12 is not a single digit, the process must be repeated. Adding the 1 and the 2 yeilds 3, a single digit and also the digital root of 39.

输入描述:

    The input file will contain a list of positive integers, one per line. The integer may consist of a large number of digits. (1 <= input value <= 10^9)

输出描述:

    For each integer in the input, output its digital root on a separate line of the output.一个求数字根的问题,同样利用递归的方式解决,代码如下:

#include<stdio.h>
int root(int n){
    int s =0;
    while(n!=0){
        s=s+n%10;
        n=n/10;
    }
    return s;
}
 int main(){
     int n ;
     while(scanf("%d",&n)!=EOF){
         while(n/10>0){
             n=root(n);
         }
         printf("%d\n",n);
     }
     return 0;
 } 

这一题值得注意的是if和while的使用,在ac之前多次未得到理想结果的原因是:使用了if代替while,本题中应该先运行后再判断条件之后输出,应当注意这一点。

3、大数运算

  Today, facing the rapid development of business, SJTU recognizes that more powerful calculator should be studied, developed and appeared in future market shortly. SJTU now invites you attending such amazing research and development work.     In most business applications, the top three useful calculation operators are Addition (+), Subtraction (-) and Multiplication (×) between two given integers. Normally, you may think it is just a piece of cake. However, since some integers for calculation in business application may be very big, such as the GDP of the whole world, the calculator becomes harder to develop.     For example, if we have two integers 20 000 000 000 000 000 and 4 000 000 000 000 000, the exact results of addition, subtraction and multiplication are:     20000000000000000 + 4000000000000000 = 24 000 000 000 000 000     20000000000000000 - 4000000000000000 = 16 000 000 000 000 000     20000000000000000 × 4000000000000000 = 80 000 000 000 000 000 000 000 000 000 000     Note: SJTU prefers the exact format of the results rather than the float format or scientific remark format. For instance, we need "24000000000000000" rather than 2.4×10^16.     As a programmer in SJTU, your current task is to develop a program to obtain the exact results of the addition (a + b), subtraction (a - b) and multiplication (a × b) between two given integers a and b.

输入描述:

   Each case consists of two separate lines where the first line gives the integer a and the second gives b (|a| <10^400 and |b| < 10^400).

输出描述:

    For each case, output three separate lines showing the exact results of addition (a + b), subtraction (a - b) and multiplication (a × b) of that case, one result per lines.

示例1

输入:

20000000000000000
4000000000000000

复制输出:

24000000000000000
16000000000000000
80000000000000000000000000000000

这一部分的数字位数极大,因此不能够采用一般的int方式来进行运算,因此本次采用相应的数组以及栈进行计算。具体代码如下:

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
bool judge(vector<int> x,vector<int> y){       //构建一个bool判断符号,判断接下来要计算的数字大小
    int m =x.size();
    int n =y.size();
    if(m<n) return false;
    else if(m>n) return true;
    else{
        for(int i =m-1;i>=0;i--){
            if(x[i]<y[i]){
                return false;
            }else if(x[i]>y[i]){
                return true;
            }
        }
    }
    return true;
}
void Add(vector<int> x, vector<int> y){
    int m = x.size(), n = y.size();
    stack<int> ans;
    int carry = 0, tmp;
     for(int i = 0; i < n; i++){
        tmp = x[i] + y[i] + carry;
        ans.push(tmp % 10);
        carry = tmp / 10;
    }
    for(int i = n; i < m; i++){
        tmp = x[i] + carry;
        ans.push(tmp % 10);
        carry = tmp / 10;
    }
    if(carry != 0){
        ans.push(carry);
    }
    while(!ans.empty()){
        cout << ans.top();
        ans.pop();
    }
    cout << endl;
}
 
void Sub(vector<int> x, vector<int> y){
    int m = x.size(), n = y.size();
    stack<int> ans;
    int carry = 0, tmp;
    for(int i = 0; i < n; i++){
        tmp = x[i] - y[i] - carry;
        if(tmp < 0){
            carry = 1;
            tmp += 10;
        }else{
            carry = 0;
        }
        ans.push(tmp);
    }
    for(int i = n; i < m; i++){
        tmp = x[i] - carry;
        if(tmp < 0){
            carry = 1;
            tmp += 10;
        }else{
            carry = 0;
        }
        ans.push(tmp);
    }
    bool flag = false;
    while(!ans.empty()){
        //要注意有可能0开头,要去掉0
        if(ans.top() == 0 && flag == false){
            ans.pop();
        }else{
            flag = true;
            cout << ans.top();
            ans.pop();
        }
 
 
    }
    cout << endl;
}
 
//注意乘法的写法
void Multiply(vector<int> x, vector<int> y){
    int m = x.size(), n = y.size();
    int carry = 0, tmp;
    vector<int> ans(m + n, 0); //初始化为0
    ans.push_back(0);
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            ans[i + j] += x[i] * y[j];
        }
    }
    for(int i = 0; i < m + n + 2; i++){
        if(ans[i] > 10){
            ans[i+1] += ans[i] / 10;
            ans[i] = ans[i] % 10;
        }
    }
 
    //结果有可能以0开头
    bool flag = false;
    for(int i = m + n + 1; i >= 0; i--){
        if(!flag && ans[i] == 0){
            continue;
        }
        else{
            flag = true;
            cout << ans[i];
        }
    }
    cout << endl;
}
 
    int main(){
        string a,b;
        while(cin>>a>>b){
            int m =a.size(),n = b.size();
            vector<int> x,y;
            for(int i =m-1;i>=0;i--){
                x.push_back(a[i]-'0');
            }
             for(int i =n-1;i>=0;i--){
               y.push_back(b[i]-'0');
            }
            if(m>=n){
               Add(x,y);
            }else {
               Add(y,x);
            }
           if(judge(x,y)){
               Sub(x,y);
           } else{
               cout<<'-';
               Sub(y,x);
           }
           if(judge(x,y)){
                Multiply(x,y);
           } else{
               Multiply(y,x);
           }
        }
    }
    
    
    
    
    

总的来说代码量还是蛮大的,但中心思想都是利用栈和队列进位以及保留位数。本题是较为经典的题目,应该多次复习。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值