2021-03-17

汽水瓶

输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=100),表示小张手上的空汽水瓶数。n=0表示输入结束,你的程序不应当处理

这个问题我的想法是子程序算出每一轮上能换到的汽水瓶数目,然后叠加输出,并且剩下一个输出现有,剩下两个输出+1,但是这样要注意的是多分枝下每一个都要return。
问题还可以简化,比如下面的递归方法。
每次拿3个瓶子换到1个瓶子,再考虑总数-2的数目可以换到多少个瓶子,逐层简化到最后2/1的情况。不会有3/0的情况结束。
所以只要知道2会得1,1会return0,就可以推出所有的情况。

#include <iostream>
  
using namespace std;
  
int f(int n)
{
    if(n==1) return 0;
    if(n==2) return 1;
    return f(n-2)+1;
}
  
int main()
{
    int n;
    while(cin >> n){
        if(n==0)
            break;
        cout<<f(n)<<endl;
    }
    return 0;
}

貌似递归次数更少的方法:

#include<iostream>
using namespace std;

int main() {
    int n,res;
    int f(int n);
    while (cin >> n) {
        if (n == 0) {
            break;
        }
        else res=f(n);
        cout << res << endl;
    }
    return 0;
}

int f(int n) {
    if (n == 1)
        return 0;
    else if (n == 2)
        return 1;
    else return n/3+f(n % 3 + n / 3);
}
斐波拉切

另外有非0输入就判断,输入为0则跳出的大前提可以用while(cin>>x)的方式判断。
多输入识别:

while(cin>>month)
{
    cout<<fabs(month)<<endl;
}

另有对一维数组vector的使用:

#include <iostream>
#include <vector>//要加头文件
using namespace std;

int main (void) {
  int n;
  while(cin >> n) {
    vector<int> v(n+1);
    v[1] = 1; v[2] = 1;
    if (n < 3) {
      cout << v[n] << endl;
      continue;
    }
    for (int i = 3; i <= n; i++) {
      v[i] = v[i-2] + v[i-1];
    }
    cout << v[n] << endl;
  }
}
质数因子-运行速度的考量

题目描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )
最后一个数后面也要有空格
输入描述:
输入一个long型整数
输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。最后一个数后面也要有空格。

1.能运行但是大大占用计算量的错误方法:
void zhaozhi(long int x) {
    long int k = 2;
    while (x != 1 && k <= x) {
        if (x % k == 0) {
            cout << k << " ";
            x = x / k;
            k = 2;
        }
        else
            k++;
    }
}

主要存在的问题是:
每找一个因子,都要重新从2开始验证他是不是,计算量就是N*(N-1)了,当输入数据大时候会产生平方量级的大量无用搜索。
而且这里面还有大量的非质数的验证是没必要的,比如4是没必要考虑的,如果有也应该拆为22,不应该反复验证非质数的可能。
第一步减轻是K=2的没必要,应该让能除尽的每一个较小因子都除尽,再k++,形成类似于倒三角的搜索。但是这样还是不够快,当比如26=2
13,搜到13的时候要花很多无用的计算,所以应该对算法进行优化。

2.优化
#include<iostream>
using namespace std;

int main(){
    long x;
    cin>>x;
    long k=2;
    while(x!=1&&k*k<=x){
        while(x%k==0){
            cout<<k<<" ";
            x=x/k;
        }
            k++;
    }
       if(x-1) cout<<x<<" ";

    return 0;
}

k*k<=x这句是缩小计算量的关键,当k * k>=x的时候,我们应该分析,小于k的因数都已经从x中分离出去了,而目前x中可能包含的因数是k及k以上的组合,最小x是仅有k * 1,即x=k;(k,k2-1]之内都不能存在,否则在之前的k拆分时就应该输出了,所以另外的情况就是x>=k2,符合含有的因数都是k及k以上。
所以如果x=k,就直接可以输出最后一个质数——目前的x本身;否则继续拆分循环k++。
注意当x=1时,要结束寻找,并且不输出1。所以用if(x-1)判断是否输出。
缺陷:在k++的遍历过程中,没有去除不是质数的k,消耗了计算。
但是判断是不是质数这个过程中用到的就是拆分的想法,如果加上判断反而比判断不是因数直接跳过更繁琐,所以没必要。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值