写一个程序,要求功能:求出用1,2,5这三个不同个数组合的和为100的组合个数。
如:100个1是一个组合,5个1加19个5是一个组合。。。
最容易想到的程序是:
1 #include<stdio.h> 2 int main() 3 { 4 int num=0; 5 for(int x=0;x<=100;x++) 6 for(int y=0;y<=50;y++) 7 for(int z=0;z<=20;z++) 8 if(x+2*y+5*z==100) 9 { 10 printf("%d\t%d\t%d",x,y,z); 11 printf("\n"); 12 num++; 13 } 14 15 printf("%d",num); 16 }
但上面这个程序一共要循环100*50*20次,效率太低了。
通过x+2y+5z=100找其中的规律。
x+5z=100-2y,由此可知,x+5z是偶数,且(x+5z)<=100
由此对z作循环,求x的可能值如下:
z=0;x=100(y=0),98(y=1),96(y=2),.....0(y=50)
z=1;x=95(y=0),93(y=1),91(y=2)......1(y=47)
.......
z=19;x=5(y=0),3(y=1),1(y=2)
z=20;x=0(y=0)
从上面的规律可以看出,组合总数为100以内的偶数+95内的奇数+90以内的偶数+。。。+5以内的奇数+1.
即为:51+48+。。。。+3+1
某个偶数m以内的偶数的个数(包括0)可以表示为(m+2)/2
某个奇数m以内的奇数的个数也可以表示为(m+2)/2
所以组合数也就可以很轻松地算出来
1 #include<stdio.h> 2 int main() 3 { 4 int num=0; 5 for(int m=0;m<=100;m+=5) 6 num+=(m+2)/2; 7 printf("%d\n",num); 8 }
再将这道题与百钱买百鸡的问题进行比较。
百钱买百鸡的问题算是一套非常经典的不定方程的问题,题目很简单:公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用100文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱。
简单的算法:
1 #include<stdio.h> 2 int main() 3 { 4 for(int x=1;x<20;x++) 5 for(int y=1;y<33;y++) 6 { 7 int z=100-x-y; 8 if((z%3==0)&&(x*5+y*3+z/3==100)) 9 { 10 printf("公鸡:%d,母鸡:%d,小鸡:%d",x,y,z); 11 printf("\n"); 12 } 13 } 14 15 }
时间复杂度较大,需要优化。
分析:
有两个方程式:
x+y+z=100 (1)
5x+3y+z/3=100 (2)
联立两个方程组可得
7x+4y=100
y=(100-7x)/4
设x=4k (1=<k<5)
则y=25-7k
z=75+3k (代入(1)式得)
再通过第二个方程式,算的k的值,k的值算出来了,x,y,z也就相应地算出来了。
初中做过的联立方程式求解的问题,应该很熟悉了。
1 #include<stdio.h> 2 int main() 3 { 4 for(int k=1;k<4;k++) 5 if((5*4*k+3*(25-7*k)+(75+3*k)/3)==100) 6 { 7 printf("公鸡:%d,母鸡:%d,小鸡:%d",4*k,(25-7*k),75+3*k); 8 printf("\n"); 9 } 10 }
总结:
这类题属于求方程式的解的问题,相对来说,第二题比较好解,也能较容易地想到优化的办法,第一道题,只有一个方程式,然后去找规律,说实话,不好好分析,还真看不出来。