1. 程式人生 > >演算法競賽入門經典習題2-2 水仙花數 2-3韓信點兵

演算法競賽入門經典習題2-2 水仙花數 2-3韓信點兵

演算法競賽入門經典習題2-2 水仙花數
重定向版並不需要#define LOCAL,fopen版要有檔案才能開啟

</pre><pre code_snippet_id="217260" snippet_file_name="blog_20140304_1_1775024" name="code" class="cpp"></pre><pre code_snippet_id="217260" snippet_file_name="blog_20140304_1_1775024" name="code" class="cpp">/*#include<cstdio>
#pragma warning(disable:4966)
void main()
{
	for(int n=100;n<1000;n++)
	{
		int ge=n%10;
		int shi=(n/10)%10;
		int bai=n/100;
		int s=ge*ge*ge+shi*shi*shi+bai*bai*bai;
		if(s==n)
			printf("%d ",n);
	}
}*/
//#define LOCAL//C4966的錯誤
#include<cstdio>
#pragma warning(disable:4966)
void main()
{
	FILE *fout;
	fout=fopen("data.out","wb");
	for(int n=100;n<1000;n++)
	{
		int ge=n%10;
		int shi=(n/10)%10;
		int bai=n/100;
		int s=ge*ge*ge+shi*shi*shi+bai*bai*bai;
		if(s==n)
			fprintf(fout,"%d ",n);
	}
	fclose(fout);
}
//#define LOCAL//編譯選項中定義
/*#include<cstdio>
#pragma warning(disable:4966)
void main()
{
#ifdef LOCAL 
	freopen("daffodil.out","w",stdout);     
#endif 
	for(int n=100;n<1000;n++)
	{
		int ge=n%10;
		int shi=(n/10)%10;
		int bai=n/100;
		int s=ge*ge*ge+shi*shi*shi+bai*bai*bai;
		if(s==n)
			printf("%d ",n);
	}
}*/
/*#pragma warning(disable:4966)
#include<cstdio>

int main()
{
    FILE *fout;
fout=fopen("daffodil.out","wb");
int a,b,c,m;
for(a=1;a<=9;a++)
    {
for(b=0;b<=9;b++)
         {
for(c=0;c<=9;c++)
              {
                   m=a*a*a+b*b*b+c*c*c;
if(m==a*100+b*10+c)
fprintf(fout,"%d\r\n",m);
              }
         }
    }
fclose(fout);
return 0;
}
*/

演算法競賽入門經典2-3韓信點兵

主要是要知道解決此題的演算法:

信點兵是一個有趣的猜數遊戲。如果你隨便拿一把蠶豆(數目約在100粒左右),先3粒3粒地數,直到不滿3粒時,把餘數記下來;第二次再5粒5粒地數,最後把餘數記下來;第三次是7粒一數,把餘數記下來。然後根據每次的餘數,就可以知道你原來拿了多少粒蠶豆了。不信的話,你還可以試驗一下。例如,假如3粒一數餘1粒,5粒一數餘2粒,7粒一數餘2粒,那麼,原有蠶豆有多少粒呢? 

這類題目看起來是很難計算的,可是我國古時候卻流傳著一種演算法,名稱也很多,宋朝周密叫它“鬼谷算”,又名“隔牆算”;楊輝叫它“剪管術”;而比較通行的名稱是“韓信點兵”。最初記述這類演算法的是一本名叫《孫子算經》的書,後來在宋朝經過數學家秦九韶的推廣,又發現了一種演算法,叫做“大衍求一術”。這在數學史上是極有名的問題,外國人一般把它稱為“中國剩餘定理”。至於它的演算法,在《孫子算經》上就已經有了說明,而且後來還流傳著這麼一道歌訣: 

三人同行七十稀, 

五樹梅花廿一枝, 

七子團圓正半月, 

除百零五便得知。 

這就是韓信點兵的計算方法,它的意思是:凡是用3個一數剩下的餘數,將它用70去乘(因為70是5與7的倍數,而又是以3去除餘1的數);5個一數剩下的餘數,將它用21去乘(因為21是3與7的倍數,又是以5去除餘1的數);7個一數剩下的餘數,將它用15去乘(因為15是3與5的倍數,又是以7去除餘1的數),將這些數加起來,若超過105,就減掉105,如果剩下來的數目還是比105大,就再減去105,直到得數比105小為止。這樣,所得的數就是原來的數了。根據這個道理,你可以很容易地把前面的五個題目列成算式: 

1×70+2×21+2×15-105 

=142-105 

=37 

因此,你可以知道,原來這一堆蠶豆有37粒。 

1900年,德國大數學家大衛·希爾伯特歸納了當時世界上尚未解決的最困難的23個難題。後來,其中的第十問題在70年代被解決了,這是近代數學的五個重大成就。據證明人說,在解決問題的過程中,他是受到了“中國剩餘定理”的啟發的。
#include<cstdio>
#pragma warning(disable:4996)
void main()
{
	FILE *fin,*fout;
	fin=fopen("data.in","rb");
	fout=fopen("data.out","wb");
	int a,b,c;
	int result;
	scanf("%d %d %d",&a,&b,&c);
	result=a*70+b*21+c*15;
	while(result>100)
		result-=105;
	if(result<10)
		fprintf(fout,"No answer\n");
	else
		fprintf(fout,"%d\n",result);
	fclose(fin);
	fclose(fout);
}//要有data.in的檔案
//#define LOCAL
/*#include<cstdio>
#pragma warning(disable:4996)
#include<iostream>
using namespace std;
int main()
{
#ifdef LOCAL
	freopen("data.in","r",stdin);
	freopen("data.out","w",stdout);
#endif
	int a,b,c;
	int result;
	//scanf("%d%d%d",&a,&b,&c);
	cin>>a>>b>>c;
	result=a*70+b*21+c*15;
	while(result>100)
		result-=105;
	if(result<10)
		printf("No answer\n");
	else
		printf("%d\n",result);
		fclose(stdin);
		fclose(stdout);
	return 0;
}*/
/*#pragma warning(disable:4996)
#include<stdio.h>
int main()
{
    FILE *fin,*fout;
fin=fopen("hanxin.in","rb");
fout=fopen("hanxin.out","wb");
    //fin=stdin;
    //fout=stdout;
int a,b,c,x,temp=0;//temp用來判斷是否在10到100記憶體在這樣的數
fscanf(fin,"%d%d%d",&a,&b,&c);
for(x=10;x<=100;x++)
    {
if(x%3==a&&x%5==b&&x%7==c)
    {
fprintf(fout,"%d\r\n",x);
temp=1;
break;
    }
    }
if(!temp)fprintf(fout,"No answer\r\n");
fclose(fin);
fclose(fout);
return 0;
}*/