满n送一算法

满n送一问题,顾名思义就是满了n个就送你一个。举个小学数学例子,班长买饮料,三个空瓶换一瓶,最少买几瓶?我先展示一个算法:

#include<stdio.h>
#define NUM 4      //满NUM送1 
int fun1(int n){   //通过递归在买n瓶的情况下我们可以得到多少瓶 
	if(n<NUM)
		return n;
	else
		return n+fun1(n/NUM);
}

int fun2(int a){  //需求a瓶我们要买多少瓶 
	int u;
	for(int i=0;i<=a;i++){
		if(fun1(i)>=a){
			printf("%d\n",i);
			break;
		}
	}
}

int main(){
	for(int b=1;b<=200;b++){   //所需求的瓶数b不断增加
		printf("%d:",b);
		fun2(b);
	}
}

是不是很简单?

但是!这个算法是错的。它忽略了一点。就比如说满三送一的话,假设我们买5瓶,可以得到多少瓶?5瓶中的3瓶可以换1瓶,但是余数2和换来的1又可以换一瓶,总共7瓶。但是这个算法忽略了余数2,所以结果为6,错误。也就是说它忽略了上一次计算的余数。

那么这个程序呢?

​
#include<stdio.h>
#define NUM 4      //满NUM送1 
int fun1(int n){   //通过递归在买n瓶的情况下我们可以得到多少瓶 
	if(n<NUM)
		return n;
	else
		return n+fun1((n+n%NUM)/NUM);
}

int fun2(int a){  //需求a瓶我们要买多少瓶 
	int u;
	for(int i=0;i<=a;i++){
		if(fun1(i)>=a){
			printf("%d\n",i);
			break;
		}
	}
}

int main(){
	for(int b=1;b<=200;b++){   //所需求的瓶数b不断增加
		printf("%d:",b);
		fun2(b);
	}
}

​

这个算法也是不对的,因为它加的不是上一次的余数而是本次的余数。那么要如何改正呢?由于要加上一次的余数,这时候递归就不太好用了,所以我们选择循环。

​
​
#include<stdio.h>
#define NUM 4      //满NUM送1 
int fun1(int n){   //在买n瓶的情况下我们可以得到多少瓶 
    int a=0;
    int sum=n;
    int b=0;
    while(n>0){
        a=(n+b)/NUM;
        sum=sum+a;
        b=(n+b)%NUM;
        n=n/3;
    }
    return sum;
}

int fun2(int a){  //需求a瓶我们要买多少瓶 
	int u;
	for(int i=0;i<=a;i++){
		if(fun1(i)>=a){
			printf("%d\n",i);
			break;
		}
	}
}

int main(){
	for(int b=1;b<=200;b++){   //所需求的瓶数b不断增加
		printf("%d:",b);
		fun2(b);
	}
}

​

​

这样结果就对了。然后我们发现如果满n送一,我们要买a瓶,那么结果就在a*((n-1)/n)左右。算是偷懒快速解题的思路吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值