for(k=1;k<=5;k+=2) {
a[0][1]=k;
for(m=1;m<7-k;m+=2) {
a[1][1]=m;
a[2][1]=7-k-m;
for(flag=1,n=0;flag&&n<3;n++)
if(a[n][0]+a[n][1]<7&&a[n][0]*2+a[n][1]==7)
a[n][2]=7-a[n][0]-a[n][1];
else
flag=0;
if(flag){
printf("No.%d Full basket Semi--basket Empty\n",++count);
for(n=0;n<3;n++)
printf("fisher %c: %d %d %d\n", 'A'+n,a[n][0],a[n][1],a[n][2]);
}
}
}
}
}
}
【18.有限5位数】
个位数为6且能被3整除的五位数共有多少?
#include
void main(){
long int i;
int count=0;
for(i=1000;i<9999;i++)
if(!((i*10+6)%3))
count++;
printf("count=%d\n",count);
}
【19. 8 除不尽的数】
一个自然数被8除余1,所得的商被8除也余1,再将第二次的商被8除后余7,最后得到一个商为a。
又知这个自然数被17除余4,所得的商被17除余15,最后得到一个商是a的2倍。求这个自然数。
#include
void main(){
int i;
for(i=0;;i++)
if(((i*8+7)*8+1)*8+1==(34*i+15)*17+4) {
printf("The required number is: %d\n",(34*i+15)*17+4);
break;
}
}
【20.一个奇异的三位数】
一个自然数的七进制表达式是一个三位数,而这个自然数的九进制表示也是一个三位数,且这两个三位数的数码正好相反,求这个三位数。
[题目分析与算法设计]根据题意可知,七进制和九进制表示的这全自然数的每一位一定小于7,可设其七进制数形式为kji(i、j、k的取值分别为1~6),然后设其九进制表示形式为ijk。
#include
void main(){
int i,j,k;
for(i=1;i<7;i++)
for(j=0;j<7;j++)
for(k=1;k<7;k++)
if(i*9*9+j*9+k==i+j*7+k*7*7){
printf("The special number with 3 digits is: ");
printf("%d%d%d(7)=%d%d%d(9)=%d(10)\n",k,j,i,i,j,k,i*9*9+j*9+k);
}
}
【21.4位反序数】
设N是一个四位数,它的9倍恰好是其反序数,求N。反序数就是将整数的数字倒过来形成的整数。例如:1234的反序数是4321。
#include
void main(){
int i;
for(i=1002;i<1111;i++)
if(i%10*1000+i/10%10*100+i/100%10*10+i/1000==i*9)
printf("The number satisfied stats condition is: %d\n",i);
}
【22.求车速】
一辆以固定速度行驶的汽车,司机在上午10点看到里程表上的读数是一个对称数(即这个数从左向右读和从右向左读是完全一样的),为95859。两小时后里程表上出现了一个新的对称数。问该车的速度是多少?新的对称数是多少?
[算法分析与设计]设所求对称数为i,其初值为95589,对其依次递增取值,将i值的每一位分解后与其对称位置上的数进行比较,若每个对称位置上的数皆相等,则可判定i即为所求的对称数。
#include
void main(){
int t,a[5];
long int k,i;
for(i=95860;;i++) {
for(t=0,k=100000;k>=10;t++) {
a[t]=(i%k)/(k/10);
k/=10;
}
if((a[0]==a[4])&&(a[1]==a[3])){
printf("The new symmetrical number kelometers is: %d%d%d%d%d\n", a[0],a[1],a[2],a[3],a[4]);
printf("The velocity of the car is: %.2f\n",(i-95859)/2.0);
break;
}
}
}
【23.阿姆斯特朗数】
如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋性数)。
如 407=4^3+0^3+7^3就是一个阿姆斯特朗数。试编程求1000以内的所有阿姆斯特朗数。
#include
void main(){
int i,t,k,a[3];
printf("There are follwing Armstrong number smaller than 1000:\n");
for(i=2;i<1000;i++) {
for(t=0,k=1000;k>=10;t++) {
a[t]=(i%k)/(k/10);
k/=10;
}
if(a[0]*a[0]*a[0]+a[1]*a[1]*a[1]+a[2]*a[2]*a[2]==i)
printf("%5d",i);
}
printf("\n");
}
【24.完全数】
如果一个数恰好等于它的因子之和,则称该数为“完全数”。
#include
void main(){
int a,i,m;
printf("There are following perfect numbers smaller than 1000: \n");
for(a=1;a<1000;a++) {
for(m=0,i=1;i<=a/2;i++)
if(!(a%i))
m+=i;
if(m==a)
printf("%4d",a);
}
printf("\n");
}
【26.亲密数】
如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。
#include
void main(){
int a,i,b,n;
printf("There are following friendly--numbers pair smaller than 3000:\n");
for(a=1;a<3000;a++) {
for(b=0,i=1;i<=a/2;i++)
if(!(a%i))
b+=i;
for(n=0,i=1;i<=b/2;i++)
if(!(b%i))
n+=i;
if(n==a&&a
printf("%4d..%4d ",a,b);
}
printf("\n");
}
【27.自守数】
自守数是指一个数的平方的尾数等于该数自身的自然数。请求出200000以内的自守数
#include
void main(){
long mul,number,k,ll,kk;
printf("It exists following automorphic nmbers small than 200000:\n");
for(number=0;number<200000;number++)
{
for(mul=number,k=1;(mul/=10)>0;k*=10);
kk=k*10;
mul=0;
ll=10;
while(k>0) {
mul=(mul+(number%(k*10))*(number%ll-number%(ll/10)))%kk;
k/=10;
ll*=10;
}
if(number==mul)
printf("%ld ",number);
}
printf("\n");
}
【28.回文数】
打印所有不超过n (取n<256) 的其平方具有对称性质的数(也称回文数)。
#include
void main(){
int m[16],n,i,t,count=0;
long unsigned a,k;
printf("No. number it's square(palindrome)\n");
for(n=1;n<256;n++) {
k=0;t=1;a=n*n;
for(i=1;a!=0;i++){
m[i] = a%10;
a/=10;
}
for(;i>1;i--){
k+=m[i-1]*t;
t*=10;
}
if(k==n*n)
printf("%2d%10d%10d\n",++count,n,n*n);
}
}
【29.求具有abcd=(ab+cd)^2性质的四位数】
3025这个数具有一种独特的性质:将它平分为二段,即30和25,使之相加后求平方,
即(30+25)2,恰好等于3025本身。请求出具有这样性质的全部四位数。
#include
void main(){
int n,a,b;
printf("There are following number with 4 digits satisfied condition\n");
for(n=1000;n<10000;n++) {
a=n/100;
b=n%100;
if((a+b)*(a+b)==n)
printf(" %d ",n);
}
printf("\n");
}
【30.求素数】
求素数表中1~1000之间的所有素数
#include
void main(){
int n1,nm,i,j,flag,count=0;
do{
printf("Input START and END=?");
scanf("%d%d",&n1,&nm);
}while(!(n1>0&&n1
printf("...........PRIME TABLE(%d--%d)............\n",n1,nm);
if(n1==1||n1==2){
printf("%4d",2);
n1=3;
count++;
}
for(i=n1;i<=nm;i++) {
if(!(i%2))
continue;
for(flag=1,j=3;flag&&j
if(!(i%j))
flag=0;
if(flag)
printf(++count%15?"%4d":"%4d\n",i);
}
printf("\n");
}
【31.歌德巴赫猜想】
验证:2000以内的正偶数都能够分解为两个素数之和(即验证歌德巴赫猜想对2000以内的正偶数成立。
#include
#include
int fflag(int i) {
int j;
if(i<=1) return 0;
if(i==2) return 1;
if(!(i%2)) return 0;
for(j=3;j<=(int)(sqrt((double)i)+1);j+=2)
if(!(i%j)) return 0;
return 1;
}
void main(){
int i,n;
for(i=4;i<=2000;i+=2){
for(n=2;n
if(fflag(n))
if(fflag(i-n)) {
printf("%14d=%d+%d\n",i,n,i-n);
break;
}
if(n==i)
printf("error %d\n",i);
}
}
【32.要发就发】
“1898--要发就发”。请将不超过1993的所有素数从小到大排成第一行,第二行上的每个素数都等于它右肩上的素数之差。编程求出:第二行数中是否存在这样的若干个连续的整数,它们的和恰好是1898?假好存在的话,又有几种这样的情况?
第一行:2 3 5 7 11 13 17......1979 1987 1993
第二行:1 2 2 4 2 4...... 8 6
#include
#include
#define NUM 320
int number[NUM]; //存放不超过1993的全部素数
int fun(int i){
int j;
if(i<=1) return 0; //判断是否为素数,为1是素数,为0不是素数
if(i==2) return 1;
if(!(i%2)) return 0;
for(j=3;j<=(int)(sqrt((double)i)+1);j+=2)
if(!(i%j)) return 0;
return 1;
}
void main(){
int i,j,count=0;
printf("There are following primes sequesces in first row: \n"); //列出第一行中差值为1989的所有素数组合
for(j=0,i=3;i<=1993;i+=2){ //求出不超过1993的全部素数
if(fun(i))
number[j++]=i;
}
for(j--;number[j]>1898;j--){ //从最大的素数开始向1898搜索
for(i=0;number[j]-number[i]>1898;i++); //循环查找满足条件的素数
if(number[j]-number[i]==1898) //若两个素数的差为1898,则输出
printf("(%d).%3d,.....,%d\n",++count,number[i],number[j]);
}
}
/*
There are follwing primes sequences in first row:
(1).89,......,1987
(2).53,......,1951
(3). 3,......,1901
*/
【35.素数幻方】
求四阶的素数幻方。即在一个4X4 的矩阵中,每一个格填 入一个数字,使每一行、每一列和两条对角线上的4 个数字所组成的四位数,均为可逆素数。
#include
#include
int number[210][5];
int select[110];
int array[4][5];
int count;
int selecount;
int larray[2][200];
int lcount[2];
int num(int number);
int ok(int number);
void process(int i);
void copy_num(int i);
int comp_num(int n);
int find1(int i);
int find2(void);
int find0(int num);
void p_array(void);
void main(){
int i,k,flag,cc=0,i1,i4;
printf("there are magic squares with invertable primes as follw:\n");
for(i=1001;i<9999;i+=2){ //求满足条件的可逆素数
k=i/1000;
if(k%2!=0&&k!=5&&num(i)){ //若可逆素数的第一位不是偶数或5
number[count][0]=i; //存入数组
process(count++); //分解素数的各位数字
if(number[count-1][2]%2!=0&& //若可逆素数满足放在矩阵第一行
number[count-1][3]%2!=0&& //和最后一行的条件,记录可逆素数的
number[count-1][2]!=5&& //下标,计数器加1
number[count-1][3]!=5)
select[selecount++]=count-1;
}
}
larray[0][lcount[0]++]=number[0][0]/100;//临时数组的第一行存前二位
larray[1][lcount[1]++]=number[0][0]/10; //临时数组的第二行存前三位
for(i=1;i
if(larray[0][lcount[0]-1]!=number[0][i]/100)
larray[0][lcount[0]++]=number[0][i]/100;
if(larray[1][lcount[1]-1]!=number[0][i]/10)
larray[1][lcount[1]++]=number[0][i]/10;
}
for(i1=0;i1
array[0][0]=select[i1]; //取对应的素数下标
copy_num(0); //复制分解的素数
for(array[1][0]=0;array[1][0]
copy_num(1); //复制分解的数字
if(!comp_num(2))
continue; //若每列的前两位的组成与素数相矛盾,则试探下一个数
for(array[2][0]=0;array[2][0]
copy_num(2);
if(!comp_num(3))
continue; //若每列的前三位的组成与素数相矛盾,则试探下一个数
for(i4=0;i4
array[3][0]=select[i4];
copy_num(3); //复制分解的数字
for(flag=1,i=1;flag&&i<=4;i++) //判断每列是否可逆素数
if(!find1(i))flag=0;
if(flag&&find2()) { //判断对角线是否为可逆素数
printf("No.%d\n",++cc); //输出幻方矩阵
p_array();
}
}
}
}
}
}
int num(int number){ //判断是否可逆素数
int j;
if(!ok(number)) return 0;
for(j=0;number>0;number/=10) //将素数变为反序数
j=j*10+number%10;
if(!ok(j)) return 0; //将素数变为反序数
return 1;
}
int ok(nt number){ //判断是否为素数
int i,j;
if(number%2==0) return 0;
j=sqrt((double)number)+1;
for(i=3;i<=j;i+=2)
if(number%i==0) return 0;
return 1;
}
void process(int i){ //将第i个整数分解为数字并存入数组
int j,num;
num=number[i][0];
for(j=4;j>=1;j--,num/=10)
number[i][j]=num%10;
}
void copy_num(int i){ //将array[i][0]指向的素数的各位数字复制到array[i]中
int j;
for(j=1;j<=4;j++)
array[i][j]=number[array[i][0>[j];
}
int comp_num(int n){ //判断array中每列的前n位是否与可逆素数允许的前n位矛盾
static int ii; //用内部静态变量保存前一次查找到的元素下标
static int jj; //ii:前一次查找前二位的下标,jj:前一次查找前三位的下标
int i,num,k,*p; //p:指向对应的要使用的前一次下标ii或jj
int *pcount; //pcount:指向要使用的临时数组数量的计数器
switch(n){ //根据n的值选择对应的一组控制变量
case 2:pcount=&lcount[0];p=ⅈbreak;
case 3:pcount=&lcount[1];p=&jj;break;
default:return 0;
}
for(i=1;i<=4;i++){ //对四列分别进行处理
for(num=0,k=0;k
num=num*10+array[k][i];
if(num<=larray[n-2][*p]) //与前一次最后查找到的元素进行比较
for(;*p>=0&&num
else
for(;plarray[n-2][*p];(*p)++); //否则向后找
if(*p<0||*p>=*pcount){
*p=0; return 0;
}
if(num!=larray[n-2][*p])
return 0; //前n位不是可逆素数允许的值则返回0
}
return 1;
}
int find1(int i){ //前n位不是可逆素数允许的值则返回0
int num,j;
for(num=0,j=0;j<4;j++)
num=num*10+array[j][i];
return find0(num);
}
int find2(void){ //判断对角线方向是否是可逆素数
int num1,num2,i,j;
for(num1=0,j=0;j<4;j++)
num1=num1*10+array[j][j+1];
for(num2=0,j=0,i=4;j<4;j++,i--)
num2=num2*10+array[j][i];
if(find0(num1)) return(find0(num2));
else return 0;
}
int find0(int num) { //查找是否为满足要求的可逆素数
static int j;
if(num<=number[j][0])for(;j>=0&&num
else for(;jnumber[j][0];j++);
if(j<0||j>=count){ j=0;return 0; }
if(num==number[j][0]) return 1;
else return 0;
}
void p_array(void){ //输出矩阵
int i,j;
for(i=0;i<4;i++){
for(j=1;j<=4;j++) printf("%d ",array[j]);
printf("\n");
}
}
【36.百钱百鸡问题】
中国古代数学家张丘建在他的《算经》中提出了著名的“百钱买百鸡问题”:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,问翁、母、雏各几何?
#include
void main(){
int x,y,z,j=0;
printf("Folleing are possible plans to buy 100 fowls with 100 Yuan.\n");
for(x=0;x<=20;x++)
for(y=0;y<=33;y++) {
z=100-x-y;
if(z%3==0&&5*x+3*y+z/3==100)
printf("%2d:cock=%2d hen=%2d chicken=%2d\n",++j,x,y,z);
}
}
【37.爱因斯坦的数学题】
爱因斯坦出了一道这样的数学题:有一条长阶梯,若每步跨2阶,则最最后剩一阶,若每步跨3 阶,则最后剩2阶,若每步跨5阶,则最后剩4阶,若每步跨6阶则最后剩5阶。只有每次跨7阶,最后才正好一阶不剩。请问这条阶梯共有多少阶?
#include
void main(){
int i=1;
while(!((i%2==1)&&(i%3==2)&&(i%5==4)&&(i%6==5)&&(i%7==0)))
++i;
printf("Staris_number=%d\n",i);
}
【38.年龄几何】
张三、李四、王五、刘六的年龄成一等差数列,他们四人的年龄相加是26,相乘是880,求以他们的年龄为前4项的等差数列的前20项。
#include
void main(){
int n,a,i;
printf("The series with equal difference are:\n");
for(n=1;n<=6;n++)
for(a=1;a<=4;a++)
if(4*n+6*a==26&&n*(n+a)*(n+a+a)*(n+a+a+a)==880)
for(i=0;i<20;i++)
printf("%d ",n+i*a);
}
【39.换分币】
用一元人民币兑换成1分、2分和5分硬币,共有多少种不同的兑换方法。
#include
void main(){
int i,j,k,count=1;
printf("There are follwing small exchange plans for 1 Yuan note:\n");
for(i=0;i<=100;i++)
for(j=0;j<=100-i;j+=2)
for(k=0;k<=100-i-2*j;k+=5)
if(i+j+k==100)
printf(count%4?"%d:1*%d+2*%d+5*%d\t":"%d:1*%d+2*%d+5*%d\n",count++,i,j/2,k/5);
}
【40.三色球问题】
若一个口袋中放有12个球,其中有3个红的。3个白的和6个黒的,问从中任取8个共有多少种不同的颜色搭配?
#include
void main(){
int i,j,count=0;
printf(" RED BALL WHITE BALL BLACKBALL\n");
printf("..................................................\n");
for(i=0;i<=3;i++)
for(j=0;j<=3;j++)
if((8-i-j)<=6)
printf(" %2d: %d %d %d\n",++count,i,j,8-i-j);
}
【41.马克思手稿中的数学题】
马克思手稿中有一道趣味数学问题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭花了50先令;每个男人花3先令,每个女人花2先令,每个小孩花1先令;问男人、女人和小孩各有几人?
设x,y,z分别代表男人、女人和小孩。按题目的要求,可得到下面的方程:
x+y+z=30 (1)
3x+2y+z=50 (2)
用方程程序求此不定方程的非负整数解,可先通过(2)-(1)式得:
2x+y=20 (3)
由(3)式可知,x变化范围是0~10
#include
void main()
{
int x,y,z,count=0;
printf(" Men Women Children\n");
printf("........................................\n");
for(x=0;x<=10;x++){
y=20-2*x;
z=30-x-y;
if(3*x+2*y+z==50)
printf(" %2d: %d %d %d\n",++count,x,y,z);
}
}
【42.最大公约数和最小公倍数】
求任意两个正整数的最大公约数和(GCD)和最小公倍数(LCM)
**手工方式求两个正整数的最大公约数的方法是用辗转相除法,在程序中可以模拟这种方式。
#include
void main(){
int a,b,num1,num2,temp;
printf("Input a & b : ");
scanf("%d,%d",&num1,&num2);
if(num1>num2){
temp=num1;
num1=num2;
num2=temp;
}
a=num1;
b=num2;
while(b!=0){
temp=a%b;
a=b;
b=temp;
}
printf("The GCK of %d and %d is: %d\n",num1,num2,a);
printf("The LCM of them is: %d\n",num1*num2/a);
}
【43.分数比较】
比较两个分数的大小。
#include
int zxgb(int a,int b){
long int c;
int d;
if(a
c=a;
a=b;
b=c;
}
for(c=a*b;b!=0;){
d=b;
b=a%b;
a=d;
}
return (int)c/a;
}
void main(){
int i,j,k,l,m,n;
printf("Please input two FENSHU: \n");
scanf("%d/%d,%d/%d",&i,&j,&k,&l);
m=zxgb(j,l)/j*i;
n=zxgb(j,l)/l*k;
if(m>n){
printf("%d/%d>%d/%d\n",i,j,k,l);
}else if(m==n){
printf("%d/%d=%d/%d\n",i,j,k,l);
}else{
printf("%d/%d<%d/%d\n",i,j,k,l);
}
}
【44.分数之和】
求这样的四个自然数p,q,r,s(p<=q<=r<=s),使得以下等式成立:
1/p+1/q+1/r+1/s=1
** 若规定p<=q<=r<=s,将原式通分、化简并整理后得到:
2<=p<5 p<=q<7 q
采用最简单的穷举方法可以很方便的求解。
#include
void main(){
int p,q,r,s,count=0;
printf("The 4 fractions which sum is equal 1 are: \n");
for(p=2;p<5;p++){
for(q=p;q<7;q++){
for(r=q;r<13;r++){
if(p*q*r-q*r-p*r-p*q!=0){
s=(p*q*r)/(p*q*r-q*r-p*r-p*q);
if(!((p*q*r)%(p*q*r-q*r-p*r-p*q))&&s>=r)
printf("[%2d] 1/%d+1/%d+1/%d+1/%d=1\n",++count,p,q,r,s);
}
}
}
}
}
/*
The 4 fractions which sum is equal 1 are:
[ 1] 1/2+1/3+1/7+1/42=1
[ 2] 1/2+1/3+1/8+1/24=1
[ 3] 1/2+1/3+1/9+1/18=1
[ 4] 1/2+1/3+1/10+1/15=1
[ 5] 1/2+1/3+1/12+1/12=1
[ 6] 1/2+1/4+1/5+1/20=1
[ 7] 1/2+1/4+1/6+1/12=1
[ 8] 1/2+1/4+1/8+1/8=1
[ 9] 1/2+1/5+1/5+1/10=1
[10] 1/2+1/6+1/6+1/6=1
[11] 1/3+1/3+1/4+1/12=1
[12] 1/3+1/3+1/6+1/6=1
[13] 1/3+1/4+1/4+1/6=1
[14] 1/4+1/4+1/4+1/4=1
Press any key to continue
*/
【45.将真分数分解为埃及分数】
分子为1 的分数称为埃及分数,现输入一个真分数,请将该分数分解为埃及分数。如:8/11=1/2+1/5+1/55+1/110。
**若真分数的分子a能整除分母b,则真分数经过化简就可以得到埃及分数,若真分数的分子不能整除分母,则可以从原来的分数中分解出一个分母为b/a+1的埃及分数。用这种方法将剩余部分反复分解,最后可得到结果。
#include
void main(){
long int a,b,c;
printf("Please enter a optional fraction(a/b): ");
scanf("%ld/%ld",&a,&b);
printf("It can be decomposed to: ");
while(1){
if(b%a){
c=b/a+1;
}else{
c=b/a;
a=1;
}
if(a==1){
printf("1/%ld\n",c);
break;
}else{
printf("1/%ld + ",c);
}
a=a*c-b;
b=b*c;
if(a==3){
printf("1/%ld + 1/%ld\n",b/2,b);
break;
}
}
}
/*
Please enter a optional fraction(a/b): 2/9
It can be decomposed to: 1/5 + 1/45
Press any key to continue
*/
【46.列出真分数序列】
按递增顺序依次列出所有分母为40,分子小于40的最简分数。
对分子采用穷举法,利用最大公约数的方法,判断分子与40是否构成真分数。
#include
void main()
{
int i,num1,num2,temp;
printf("The fraction serials with demominator 40 is: \n");
for(i=1;i<=40;i++){
num1=40;
num2=i;
while(num2!=0){
temp=num1%num2;
num1=num2;
num2=temp;
}
if(num1==1){
printf("%d/40 ",i);
}
}
}
/*
The fraction serials with demominator 40 is:
1/40 3/40 7/40 9/40 11/40 13/40 17/40 19/40 21/40 23/40 27/40 29/40
31/40 33/40 37/40 39/40 Press any key to continue
*/
【47.计算分数的精确值】
使用数组精确计算M/N(0
由于计算机字长的限制,常规的浮点运算都有精度限制,为了得到高精度的计算结果,就必须自行设计实现方法。
为了实现高精度的计算,可将商存放在一维数组中,数组的每个元素存放一位十进制数,即商的第一位存放在第一个元素中,商的第二位存放在第二个元素中....,依次类推。这样就可以使用数组不表示一个高精度的计算结果。进行除法运算时可以模拟人的手工操作,即每次求出商的第一位后,将余数乘以10,再计算商的下一位,重复以上过程,当某次计算后的余数为0 时,表示M/N为有限不循环小数某次计算后的余数与前面的某个余数相同时,
则M/N为无限循环小数,从该余数第一次出现之后所求得的各位数就是小数的循环节。程序具体实现时,采用了数组和其它一些技巧来保存除法运算所得到的余数和商的各位数。
#include
int remainder[101],quotient[101];
void main()
{
int m,n,i,j;
printf("Please input a fraction(m/n)(<0
scanf("%d/%d",&m,&n);
printf("%d/%d it\'s accuracy value is:0.",m,n);
for(i=1;i<=100;i++){
remainder[m]=i;
m*=10;
quotient[m]=m/n;
m=m%n;
if(m==0){
for(j=1;j<=1;j++){
printf("%d",quotient[j]);
}
break;
}
if(remainder[m]!=0){
for(j=1;j<=i;j++)
printf("%d",quotient[j]);
printf("\n\tand it is a infinite cyclic fraction from %d\n",remainder[m]);
printf("\tdigit to %d digit after decimal point.\n",i);
break;
}
}
}
【51.谁是窃贼】
公安人员审问四名窃贼嫌疑犯。已知,这四人当中仅有一名是窃贼,还知道这四人中每人要么是诚实的,要么总是说谎的。在回答公安人员的问题中:
甲说:“乙没有偷,是丁偷的。”
乙说:“我没有偷,是丙便的。”
丙说:“甲没有偷,是乙偷的。”
丁说:“我没有偷。”
请根据这四人的答话判断谁是盗窃者。
#include
void main(){
int i,j,a[4];
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
if(j==i){
a[j]=1;
}else{
a[j]=0;
}
}
if(a[3]+a[1]==1&&a[1]+a[2]==1&&a[0]+a[1]==1) {
printf("The thief is ");
for(j=0;j<=3;j++){
if(a[j]){
printf("%c.",j+'A');
}
}
printf("\n");
}
}
}
/*
The thief is B.
Press any key to continue
*/
【52.黑与白】
有A、B、C、D、E五人,每人额头上都帖了一张黑或白的纸。五人对坐,每人都可以看到其它人额头上的纸的颜色。五人相互观察后,
A说:“我看见有三人额头上帖的是白纸,一人额头上帖的是黑纸。”
B说:“我看见其它四人额头上帖的都是黑纸。”
C说:“我看见一人额头上帖的是白纸,其它三人额头上帖的是黑纸。”
D说:“我看见四人额头上帖的都是白纸。”
E什么也没说。
现在已知额头上帖黑纸的人说的都是谎话,额头帖白纸的人说的都是实话。问这五人谁的额头是帖白纸,谁的额头是帖黑纸?
假如变量A、B、C、D、E表示每个人额头上所帖纸的颜色,0 代表是黑色,1 代表是白色。根据题目中A、B、C、D四人所说的话可以总结出下列关系:
A说: a&&b+c+d+e==3||!a&&b+c+d+e!=3
B说: b&&a+c+d+e==0||!b&&a+c+d+e!=0
C说: c&&a+b+d+e==1||!c&&a+b+d+e!=1
D说: d&&a+b+c+e==4||!d&&a+b+c+e!=4
穷举每个人额头所帖纸的颜色的所有可能的情况,代入上述表达式中进行推理运算,使上述表达式为“真”的情况就是正确的结果。
#include
void main(){
int a,b,c,d,e;
for(a=0;a<=1;a++)
for(b=0;b<=1;b++)
for(c=0;c<=1;c++)
for(d=0;d<=1;d++)
for(e=0;e<=1;e++)
if((a&&b+c+d+e==3||!a&&b+c+d+e!=3)&&(b&&a+c+d+e==0||!b&&a+c+d+e!=0) &&(c&&a+b+d+e==1||!c&&a+b+d+e!=1)&&(d&&a+b+c+e==4||!d&&a+b+c+e!=4)){
printf("A is pasted a piece of %s paper on his forehead.\n",a?"white":"black");
printf("B is pasted a piece of %s paper on his forehead.\n",b?"white":"black");
printf("C is pasted a piece of %s paper on his forehead.\n",c?"white":"black");
printf("D is pasted a piece of %s paper on his forehead.\n",d?"white":"black");
printf("E is pasted a piece of %s paper on his forehead.\n",e?"white":"black");
}
}
/*
A is pasted a piece of black paper on his forehead.
B is pasted a piece of black paper on his forehead.
C is pasted a piece of white paper on his forehead.
D is pasted a piece of black paper on his forehead.
E is pasted a piece of white paper on his forehead.
Press any key to continue
*/
【53.迷语博士的难题(1)】
诚实族和说谎族是来自两个荒岛的不同民族,诚实族的人永远说真话,而说谎族的人永远说假话。迷语博士是个聪明的人,他要来判断所遇到的人是来自哪个民族的。迷语博士遇到三个人,知道他们可能是来自诚实族或说谎族的。为了调查这三个人是什么族的,博士分别问了他们的问题,这是他们的对话:
问第一个人:“你们是什么族?”,答:“我们之中有两个来自诚实族。”第二个人说:“不要胡说,我们三个人中只有一个是诚实族的。”第三个人听了第个人的话后说:“对,就是只有一个诚实族的。”请根据他的回答判断他们分别是哪个族的。
**假设这三个人分别为A、B、C,若说谎其值为0,若诚实,其值为1。根据题目中三个人的话可分别列出:
第一个人: a&&a+b+c==2||!a&&a+b+c!=2
第二个人: b&&a+b+c==1||!b&&a+b+c!=1
第三个人: c&&a+b+c==1||!c&&a+b+c!=1
利用穷举法,可以很容易地推出结果。
#include
void main(){
int a,b,c;
for(a=0;a<=1;a++)
for(b=0;b<=1;b++)
for(c=0;c<=1;c++)
if((a&&a+b+c==2||!a&&a+b+c!=2)&&(b&&a+b+c==1||!b&&a+b+c!=1)&&(c&&a+b+c==1||!c&&a+b+c!=1)){
printf("A is a %s.\n",a?"honest":"lier");
printf("B is a %s.\n",b?"honest":"lier");
printf("C is a %s.\n",c?"honest":"lier");
}
}
/*
A is a lier.
B is a lier.
C is a lier.
Press any key to continue
*/
【54.迷语博士的难题(2)】
两面族是荒岛上的一个新民族,他们的特点是说话真一句假一句且真假交替。如果第一句为真,则第二句是假;如果第一句为假的,则第二句就是真的,但是第一句是真是假没有规律。
迷语博士遇到三个人,知道他们分别来自三个不同的民族:诚实族、说谎族和两面族。三人并肩站在博士前面。
博士问左边的人:“中间的人是什么族的?”,左边的人回答:“诚实族的”。
博士问中间的人:“你是什么族的?”,中间的人回答:“两面族的”。
博士问右边的人:“中间的人究竟是什么族的?”,右边的人回答:“说谎族的”。
请问:这三个人都是哪个民族的?
这个问题是两面族问题中最基本的问题,它比前面只有诚实族和说谎族的问题要复杂。解题时要使用变量将这三个民族分别表示出来。
令:变量A=1表示:左边的人是诚实族的(用C语言表示为A);
变量B=1表示:中间的人是诚实族的(用C语言表示为B);
变量C=1表示:右边的人是诚实族的(用C语言表示为C);
变量AA=1表示:左边的人是两面族的(用C语言表示为AA);
变量BB=1表示:中间的人是两面族的(用C语言表示为BB);
变量CC=1表示:右边的人是两面族的(用C语言表示为CC);
则左边的人是说谎族可以表示为:A!=1且AA!=1 (不是诚实族和两面族的人)
用C语言表示为:!A&&!AA
中间的人是说谎族可以表示为:B!=1且BB!=1
用C语言表示为:!B&&!BB
右边的人是说谎族可以表示为:C!=0且CC!=1
用C语言表示为:!C&&!CC
根据题目中“三人来自三个民族”的条件,可以列出:
a+aa!=2&&b+bb!=2&&c+cc!=2 且 a+b+c==1&&aa+bb+cc==1
根据左边人的回答可以推出:若他们是诚实族,则中间的人也是诚实族;若他不是诚实族,则中间的人也不是诚实族。以上条件可以表示为:
c&&!b&&!bb||(!c&&!cc)&&(b||bb)||!c&&cc
将全部逻辑条件联合在一起,利用穷举的方法求解,凡是使上述条件同时成立的变量取值就是题目的答案。
#include
void main(){
int a,b,c,aa,bb,cc;
for(a=0;a<=1;a++)
for(b=0;b<=1;b++)
for(c=0;c<=1;c++)
for(aa=0;aa<=1;aa++)
for(bb=0;bb<=1;bb++)
for(cc=0;cc<=1;cc++)
if(a+aa!=2&&b+bb!=2&&c+cc!=2&&a+b+c==1&&aa+bb+cc==1
&&(a&&!aa&&b&&!bb||!a&&!b)&&!b &&(c&&!b&&!bb||(!c&&!cc)&&(b||bb)||!c&cc)){
printf("The man stand on left is a %s.\n",aa?"double--dealer":(a?"honest":"lier"));
printf("The man stand on left is a %s.\n",bb?"double--dealer":(b?"honest":"lier"));
printf("The man stand on left is a %s.\n",cc?"double--dealer":(c?"honest":"lier"));
}
}
/*
The man stand on left is a double--dealer.
The man stand on left is a lier.
The man stand on left is a honest.
Press any key to continue
*/
【55.哪个大夫哪天值班】
医院有A、B、C、D、E、F、G七位大夫,在一星期内(星期一至星期天)每人要轮流值班一天。现在已知:
A大夫比C大夫晚一天值班;
D大夫比E大夫晚二天值班;
B大夫比G大夫早三天值班;
F大夫的值班日在B和C大夫的中间,且是星期四;
请确定每天究竟是哪位大夫值班?
** 由题目可推出如下已知条件:
*F是星期四值班;
*B值班的日期在星期一至星期三,且三天后是G值班;
*C值班的日期在星期五至星期六,且一天后是A值班;
*E两天后是D值班;E值班的日期只能在星期一至星期三;
在编程时用数组元素的下标1到7表示星期一到星期天,用数组元素的值分别表示A~F七位大夫。
#include
#include
int a[8];
char *day[]={"","MONDAY","TUESDAY","WEDNESDAY","THURSDAYT","FRIDAY","SATUDAY","SUNDAY"};
int main(){
int i,j,t;
a[4]=6;
for(i=1;i<=3;i++){
a[i]=2;
if(!a[i+3]){
a[i+3]=7;
}else{
a[i]=0;
continue;
}
for(t=1;t<=3;t++){
if(!a[t]){
a[t]=5;
}else{
continue;
}
if(!a[t+2]){
a[t+2]=4;
}else{
a[t]=0;
continue;
}
for(j=5;j<7;j++){
if(!a[j]){
a[j]=3;
}else
continue;
if(!a[j+1]){
a[j+1]=1;
}else{
a[j]=0;
continue;
}
for(i=1;i<=7;i++){
printf("Doctor %c is on duty %s.\n",'A'+a[i]-1,day[i]);
}
exit(0);
}
}
}
}
/*
Doctor E is on duty MONDAY.
Doctor B is on duty TUESDAY.
Doctor D is on duty WEDNESDAY.
Doctor F is on duty THURSDAYT.
Doctor G is on duty FRIDAY.
Doctor C is on duty SATUDAY.
Doctor A is on duty SUNDAY.
Press any key to continue
*/
【56.区分旅客国籍】
在一个旅馆中住着六个不同国籍的人,他们分别来自美国、德国、英国、法国、俄罗斯和意大利。他们的名字叫A、B、C、D、E和F。名字的顺序与上面的国籍不一定是相互对应的。现在已知:
1)A和美国人是医生。
2)E和俄罗斯人是技师。
3)C和德国人是技师。
4)B和F曾经当过兵,而德国人从未参过军。
5)法国人比A年龄大;意大利人比C年龄大。
6)B同美国人下周要去西安旅行,而C同法国人下周要去杭州度假。
试问由上述已知条件,A、B、C、D、E和F各是哪国人?
首先进行题目分析,尽可能利用已知条件,确定谁不是哪国人。
由:1) 2) 3)可知:A不是美国人,E不是俄罗斯人,C不是德国人。另外因为A与德国人的职业不同,E与美、德人的职业不同,C与美、俄人的职业不同,故A不是俄罗斯人或德国 人,E不是美国人或德国人,C不是美国人或俄罗斯人。
由4)和5)可知B和F不是德国人,A不是法国人,C不是意大利人。
由6)可知B不是美国人,也不是法国人(因B与法国人下周的旅行地点不同);C不是法国人。
将以上结果汇总可以得到下列条件矩阵:
. 美(医生) 英 法 德(技师) 意大利 俄(教师)
A(医生) X . X X . X
B X . X X . .
C(技师) X . X X X X
D . . . . . .
E(教师) X . . X . X
F . . . X . .
根据此表使用消元法进行求解,可以方便地得到问题的答案。
#include
int main(void){
char *m[7] = {"","U.S","U.K","FRANCE","GER","ITALY","EUSSIAN"};
//国名
char b;
int a[7][7],i,j,k,n,t,e,x,y;
for(i = 0;i < 7;i++){ //初始化条件矩阵
for(j = 0;j < 7;j++){ //行为人,列为国家,元素的值表示某人是该国人
a[i][j] = j;
}
}
for(i = 1;i < 7;i++){ //条件矩阵每一列的第0号元素作为该列数据处理的标记
a[0][i] = 1; //标记该列尚未处理
}
a[1][1] = a[2][1] = a[3][1] = a[5][1] = 0; //输入条件矩阵中的各种条件,0代表不是该国人
a[1][3] = a[2][3] = a[3][3] = 0;
a[1][4] = a[2][4] = a[3][4] = a[5][4] = a[6][4] = 0;
a[3][5] = 0;
a[1][6] = a[3][6] = a[5][6] = 0;
while(a[0][1]+a[0][2]+a[0][3]+a[0][4]+a[0][5]+a[0][6] > 0){ //当六列处理完毕后退出循环
for(i = 1;i < 7;i++){ //i:列坐标
if(a[0][i]){ //若该列未处理,则进行处理
for(e = 0,j = 1;j < 7;j++){
if(a[j][i]){ //j:行坐标 e:该列中非0原计数器
x = j;
y = i;
e++;
}
}
if(e == 1){ //该列只有一个元素非零,则进行行消去操作
for(t = 1;t < 7;t++){
if(t != i){
a[x][t] = 0;//将非零元素所在的行的其他元素置0
}
}
a[0][y] = 0; //设置该列已处理完毕的标记
}
}
}
}
for(i = 1;i < 7;i++){ //输出推理结果
printf("%c is coming from ",'A'-1+i);
for(j = 1;j < 7;j++){
if(a[i][j] != 0){
printf("%s.\n",m[a[i][j]]);
break;
}
}
}
return 0;
}
/*
A is coming from ITALY.
B is coming from EUSSIAN.
C is coming from U.K.
D is coming from GER.
E is coming from FRANCE.
F is coming from U.S.
Press any key to continue
*/
【57.谁家孩子跑最慢】
张王李三家各有三个小孩。一天,三家的九个孩子在一起比赛短跑,规定不分年龄大小,跑第一得9分,跑第2得8分,依此类推。比赛结果各家的总分相同,且这些孩子没有同时到达终点的,也没有一家的两个或三个孩子获得相连的名次。已知获第一名的是李家的孩子,获得第二的是王家的孩子。问获得最后一名的是谁家的孩子?
按题目的条件,共有1+2+3+...+9=45分,每家的孩子的得分应为15分。
根据题意可知:获第一名的是李家的孩子,获第二名的是王家的孩子,则可推出:获第三名的一定是张家的孩子。
由“这些孩子没有同时到达终点的”可知:名次不能并列,由“没有一家的两个或三个孩子获得相连的名次”可知:第四名不能是张家的孩子。
#include
int score[4][4];
void main(){
int i,j,k,who;
score[1][1]=7;
score[2][1]=8;
score[3][1]=9;
for(i=4;i<6;i++)
for(j=4;j<7;j++){
for(k=4;i!=j&&k<7;k++){
if(k!=i&&k!=j&&15-i-score[1][1]!=15-j-score[2][1]
&&15-i-score[1][1]!=15-k-score[3][1] &&15-j-score[2][1]!=15-k-score[3][1]){
score[1][2]=i;score[1][3]=15-i-7;
score[2][2]=j;score[2][3]=15-j-8;
score[3][2]=k;score[3][3]=15-k-9;
}
}
}
for(who=0,i=1;i<=3;i++,printf("\n")){
for(j=1;j<=3;j++){
printf("%d ",score[i][j]);
if(score[i][j]==1)
who=i;
}
}
if(who==1) {
printf("The last one arrived to end is a child from family Zhang.\n");
}else if(who==2){
printf("The last one arrived to end is a child from family Wang.\n");
}else {
printf("The last one arrived to end is a child from family Li.\n");
}
}
/*
7 5 3
8 6 1
9 4 2
The last one arrived to end is a child from family Wang.
Press any key to continue
*/
【58.拉丁方阵】
构造 NXN 阶的拉丁方阵(2<=N<=9),使方阵中的每一行和每一列中数字1到N只出现一次。如N=4时:
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
#include
#define N 6
void main(){
int i,j,k,t;
printf("The posible Latin Squares of order %d are: \n",N);
for(j=0;j
for(i=0;i
t=(i+j)%N;
for(k=0;k
printf("%d",(k+t)%N+1);
printf("\n");
}
printf("\n");
}
}
【59.填表格】
将1、2、3、4、5和6 填入下表中,要使得每一列右边的数字比左边的数字大,每一行下面的数字比上面的数字大。按此要求,可有几种填写方法?
. . .
. . .
#include
int count;
int jud1(int s[]){
int i,l;
for(l=1;l<4;l++)
for(i=l+1;i<5;++i)
if(s[l]==s[i])
return 0;
return 1;
}
void print(int u[]){
int k;
printf("No.:%d",++count);
for(k=0;k<6;k++)
if(k%3==0)
printf("\n%d",u[k]);
else
printf("%d",u[k]);
}
void main(){
static int a[]={1,2,3,4,5,6};
printf("The possble table satisfied above conditions are: \n");
for(a[1]=a[0]+1;a[1]<=5;++a[1]){
for(a[2]=a[1]+1;a[2]<=5;++a[2]){
for(a[3]=a[0]+1;a[3]<=5;++a[3]){
for(a[4]=a[1]>a[3]?a[1]+1:a[3]+1;a[4]<=5;++a[4]){
if(jud1(a)){
print(a);
}
}
}
}
}
}
【60.1~9分成1:2:3的三个3位数】
将1到9 这九个数字分成三个3位数,分求第一个3位数,正好是第二个3位数的二倍,是第三个3位数的三倍。问应当怎样分法。
#include
int a[9];
int ok(int t,int *z){
int *p1,*p2;
for(p1=z;p1
*p1=t%10;
t/=10;
for(p2=a;p2
if(*p1==0||*p2==*p1){
return 0;
}
}
}
return 1;
}
void main(){
int m,count=0;
for(m=123;m<=333;m++){
if(ok(m,a)&&ok(2*m,a+3)&&ok(3*m,a+6)) {
printf("No.%d: %d %d %d\n",++count,m,2*m,3*m);
}
}
}
/*
No.1: 192 384 576
No.2: 219 438 657
No.3: 273 546 819
No.4: 327 654 981
Press any key to continue
*/
【61.1~9组成三个3位的平方数】
将1、2、3、4、5、6、7、8、9九个数字分成三组,每个数字只能用一次,即每组三个数不允许有重复数字,也不许同其它组的三个数字重复,要求每组中的三位数都组成一个平方数。
#include
int main(){
int a[20], num[20][3], b[10];
int i, j, k, m, n, t, flag;
printf("The 3 squares with 3 different digits each are:\n");
for (j = 0, i =11; i <= 31; i++){
if (0 != i % 10){
k = i * i;
num[j+1][0] = k / 100;
num[j+1][1] = k / 10 % 10;
num[j+1][2] = k % 10;
if (num[j+1][0] != num[j+1][1] && num[j+1][0] != num[j+1][2] && num[j+1][1] != num[j+1][2]){
a[++j] = k;
}
}
}
for (i = 1; i <= j-2; i++){
b[1] = num[i][0];
b[2] = num[i][1];
b[3] = num[i][2];
for (t = i + 1; t <= j-1; t++){
b[4] = num[t][0];
b[5] = num[t][1];
b[6] = num[t][2];
for (flag = 0, m = 1; !flag && m <= 3; m++){
for (n = 4; !flag && n <= 6; n++)
if (b[m] == b[n])
flag = 1;
}
if (!flag){
for (k = t + 1; k <= j; k++){
b[7] = num[k][0];
b[8] = num[k][1];
b[9] = num[k][2];
for (flag = 0, m = 1; !flag && m <= 6; m++){
for (n = 7; !flag && n <= 9; n++)
if (b[m] == b[n])
flag = 1;
}
if (!flag){
printf("%d %d %d\n", a[i], a[t], a[k]);
}
}
}
}
}
return 0;
}
/*
The 3 squares with 3 different digits each are:
361 529 784
Press any key to continue
*/
【62.由8个整数形成奇特的立方体】
任意给出8个整数,将这8个整数分别放在一个立方体的八个顶点上,要求每个面上的四个数之和相等。
#include
#include
void main(){
int a[9],ii=0,i,a1,a2,a3,a4,b1,b2,b3,b4,flag;
for(i=1;i<=8;i++) {
printf("Please enter [%d]number:",i);
scanf("%d",&a[i]);
ii+=a[i];
}
printf("******************************************\n");
if(ii%2){
printf("Sorry they can't be constructed required cube!\n");
exit(0);
}
for(flag=0,a1=1;a1<=8;a1++) {
for(a2=1;a2<=8;a2++)
if(a2!=a1)
for(a3=1;a3<=8;a3++)
if(a3!=a2&&a3!=a1)
for(a4=1;a4<=8;a4++)
if(a4!=a3&&a4!=a2&&a4!=a1)
for(b1=1;b1<=8;b1++)
if(b1!=a4&&b1!=a3&&b1!=a2&&b1!=a1)
for(b2=1;b2<=8;b2++)
if(b2!=b1&&b2!=a4&&b2!=a3&&b2!=a2&&b2!=a1)
for(b3=1;b3<=8;b3++)
if(b3!=b2&&b3!=b1&&b3!=a4&&b3!=a3&&b3!=a2&&b3!=a1)
for(b4=1;b4<=8;b4++)
if(b4!=b2&&b4!=b1&&b4!=b3&&b4!=a4&&b4!=a3&&b4!=a2&&b4!=a1)
if(a[b1]+a[b2]+a[b3]+a[b4]==ii/2 && a[a1]+a[a2]+a[b1]+a[b2]==ii/2 && a[a1]+a[a4]+a[b1]+a[b4]==ii/2){
flag=1;goto out;
}
}
out:
if(flag){
printf("They can be constructed required cube as follow:\n");
printf(" %2d/----------/%2d\n",a[a4],a[a3]);
printf(" %2d/----------/%2d|\n",a[a1],a[a2]);
printf(" | | | |\n");
printf(" | | | |\n");
printf(" | %2d | %2d\n",a[b4],a[b3]);
printf(" | /--------|-/\n");
printf(" %2d/----------/%2d\n",a[b1],a[b2]);
}
else printf("Sorry they can't be constructed required cube!\n");
}
/*
Please enter [1]number:20
Please enter [2]number:21
Please enter [3]number:22
Please enter [4]number:23
Please enter [5]number:24
Please enter [6]number:25
Please enter [7]number:26
Please enter [8]number:27
******************************************
They can be constructed required cube as follow:
27/----------/24
20/----------/23|
| | | |
| | | |
| 22 | 21
| /--------|-/
25/----------/26
Press any key to continue
*/
【63.减式还原】
编写程序求解下式中各字母所代表的数字,不同的字母代表不同的数字。
PEAR
- ARA
--------
PEA
#include
void main(){
int p,e,a,r;
for(p=1;p<=9;p++)
for(e=0;e<=9;e++)
if(p!=e)
for(a=1;a<=9;a++)
if(a!=p&&a!=e)
for(r=0;r<=9;r++)
if(r!=p&&r!=e&&r!=a&&p*1000+e*100+a*10+r-(a*100+r*10+a)==p*100+e*10+a){
printf(" PEAR %d%d%d%d\n",p,e,a,r);
printf(" - ARA - %d%d%d\n",a,r,a);
printf(" ------- ---------\n");
printf(" PEA %d%d%d\n",p,e,a);
}
}
/*
PEAR 1098
- ARA - 989
------- ---------
PEA 109
Press any key to continue
*/
【64.乘式还原】
A代表数字0到9中的前五个数字,Z代表后五个数字,请还原下列乘式。
A Z A
× A A Z
------------
A A A A
A A Z Z
Z A A
------------
Z A Z A A
#include
void print(long a,long b,long s1,long s2,long s3){
printf("\n %ld\n",a);
printf("* %ld\n",b);
printf("---------------\n");
printf(" %ld\n %ld\n %ld\n",s1,s2/10,s3/100);
printf("---------------\n");
printf(" %ld\n",a*b);
}
int jud(long q,char *pflag){
while(q!=0&&*pflag!=NULL)
if(*pflag-'0'!=(q%10>=5?1:0))
return 0;
else{
q/=10;++pflag;
}
if(q==0&&*pflag==NULL)
return 1;
else
return 0;
}
void main(){
long i,j,k,l,m,n,term,t1,t2,t3;
int flag;
for(i=0;i<=4;++i){
for(j=5;j<=9;++j){
for(k=0;k<=4;++k){
term=100*i+10*j+k;
for(flag=0,n=0;n<4&&!flag;){
flag=jud((t3=++n*100*term)/100,"001");
}
if(flag){
for(flag=0,m=0;m<4&&!flag;){
flag=jud((t2=++m*10*term)/10,"1100");
}
if(flag){
for(flag=0,l=5;l<9&&!flag;){
flag=jud(t1=++l*term,"0000");
}
if(flag&&jud(t1+t2+t3,"00101")) {
print(term,n*100+m*10+l,t1,t2,t3);
}
}
}
}
}
}
}
/*
372
* 246
---------------
2232
1488
744
---------------
91512
Press any key to continue
*/
【65.乘式还原(2)】
有乘法算式如下:
○○○
× ○○
------------
○○○○
○○○○
------------
○○○○○
#include
#define NUM 5
#define C_NUM 4
int a[NUM+1];
int b[]={0, 2, 3, 5, 7};
int f(long sum);
int main() {
int i, not_finish = 1;
i = 2;
a[1] = 1;
while(not_finish){
while(not_finish&&i<=NUM){
if(a[i] >= C_NUM){
if(i == 1 && a[1] == C_NUM){
not_finish = 0;
}
else{
a[i--] = 0;
}
}
else{
a[i++]++;
}
}
if(not_finish){
long int sum1, sum2, sum3, sum4;
sum1 = b[a[1]] * 100 + b[a[2]] * 10 + b[a[3]];
sum2 = sum1 * b[a[5]];
sum3 = sum1 * b[a[4]];
if(sum2 >= 2222 && sum2 <= 7777 && f(sum2) && sum3 >= 2222 && sum3 <= 7777 && f(sum3))
if((sum4 = sum2 + sum3 * 10) >= 22222 && sum4 <= 77777 && f(sum4)){
printf(" %d\n", sum1);
printf("* %d%d\n", b[a[4]], b[a[5]]);
printf("........................\n");
printf(" %d\n", sum2);
printf(" %d\n", sum3);
printf("........................\n");
printf(" %d\n", sum4);
}
i = NUM;
}
}
return 0;
}
int f(long sum) {
int i, k, flag;
while(sum > 0){
i = sum % 10;
for (flag = 0,k = 1;!flag && k <= C_NUM; k++){
if(b[k] == i){
flag = 1;
break;
}
}
if(!flag){
return 0;
}
else{
sum = sum / 10;
}
}
return 1;
}
/*
775
* 33
........................
2325
2325
........................
25575
Press any key to continue
*/
【66.除式还原(1)】
给定下列除式,其中包含5个7,其它打×的是任意数字,请加以还原。
× 7 × --------------商
--------------
除数------××| ×××××-------------被除数
×7 7
--------------
× 7 ×
× 7 ×
----------
× ×
× ×
----------
○
**首先分析题目,由除式本身尽可能多地推出已知条件。由除式本身书已知:
1、被除数的范围是10000到99999,除数的范围是10到99,且可以整除;
2、商为100到999之间,且十位数字为7;
3、商的第一位与除数的积为三位数,且后两位为77;
4、被除数的第三位一定为4;
5、 7乘以除数的积为一个三位数,且第二位为7;
6、商的最后一位不能为0,且与除数的积为一个二位数。
由已知条件就可以采用穷举的方法找出结果。
#include
void main(){
long int i;
int j,l;
for(i=10000;i<=99999;i++)
if(i%1000-i%100==400)
for(j=10;j<=99;j++)
if(i%j==0&&(l=i/j)%100>=70&&l%100<80&&l%10!=0&&l>100&&l<=999)
if((j*(l%10))<100&&j*(l%10)>10)
if(j*7%100>=70&&j*7%100<80)
if(j*(l/100)%100==77&&j*(l/100)>100)
printf("%ld/%ld=%d\n",i,j,l);
}
/*
51463/53=971
Press any key to continue
*/
【67.除式还原(2)】
下列除式中仅在商中给定了一个7,其它打×的位置全部是任意数字,请还原。
×7××× -------------商
------------------
除数 -------------------×××| ×××××××× -------------被除数
×××× -------------1)
---------------
××× -------------2)
××× -------------3)
---------------
×××× -------------4)
××× -------------5)
-----------------
×××× -------------6)
×××× -------------7)
-----------------
0
这道题是不可能用单纯的穷举法求解的,一则计算时间太长,二则难于求出除式中各部分的值。对除式进行分析,改可能多地推出限制条件:
由3)可以看出,商的第二位7乘除数得一个三位数,所以除数<=142。
由除数乘商的第一位为一个四位数可知,商的第一位只能为8或9且除数>=112。同时商的第五位也为8或9数的前四位一定<=142*9+99且>=1000+10。
由4)、5)、6)可以看出,4)的前两位一定为“10”;5)的第一位一定为“9”;6)的前两位一定在10到99之间;商的第四位一定为为0。
由 5)的第一位一定是“9”和“112”<=除数<=142可知:商的第三位可能为7或8。
由除式本身可知:商的第四位为0。
由 1)可知:除数X商的第一位应当为一个四位数。
由 5)可知:除数X商的第三位应当为一个三位数。
编程时为了方便,将被除数分解:前四位用a[0]表示,第五位用a[1],第六位用a[2],第七八两位用a[3];除数用变量b表示;分解商:第一位用c[0],第五位用c[2];其它的部分商分别表示为:2)的前两位为d[0],4)的前三位为d[1],6)的前二位为d[2]。将上述分析用数学的方法综合起来可以表示为:
被除数: 1010<=a[0]<=1377 0<=a[1]<=9
0<=a[2]<=9 0<=a[3]<=99
除数: 112<=b <=142
商: 8<=c[0]<=9 7<=c[1]<=8 8<=c[2]<=9
2)的前两位: 10<=d[0]<=99
4)的前三位: 100<=d[1]
6)的前两位: 10<=d[2]<=99
1)式部分积: b*c[0]>1000
5)式部分积: 100
#include
void main(){
int a[4],b,c[3],d[4],i=1;
for(a[0]=1010;a[0]<=1377;a[0]++)
for(b=112;b<=142;b++)
for(c[0]=8;c[0]<=9;c[0]++)
if(b*c[0]>1000&&(d[0]=a[0]-b*c[0])>=10&&d[0]<100)
for(a[1]=0;a[1]<=9;a[1]++)
if((d[1]=d[0]*10+a[1]-b*7)>=100&&d[1]
for(a[2]=0;a[2]<=9;a[2]++)
for(c[1]=7;c[1]<=8;c[1]++)
if(b*c[1]<1000&&(d[2]=d[1]*10+a[2]-b*c[1])>=10&&d[2]<100)
for(a[3]=0;a[3]<=99;a[3]++)
for(c[2]=8;c[2]<=9;c[2]++)
if(d[2]*100+a[3]-b*c[2]==0){
printf("No%2d:",i++);
printf("%d%d%d%d%d/",a[0],a[1],a[2],a[3]/10,a[3]%10);
printf("%d=",b);
printf("%d%d%d%d%d\n",c[0],7,c[1],0,c[2]);
}
}
/*
No 1:12128316/124=97809
Press any key to continue
*/
【68.九位累进可除数】
求九位累进可除数。所谓九位累进可除数就是这样一个数:这个数用到1到9这九个数字组成,每个数字刚好只出现一次。这九个位数的前两位能被2整除,前三位能被3整除......前N位能被N整除,整个九位数能被9整除。
#include
#define NUM 9
int a[NUM+1];
int main(){
int i,k,flag,not_finish=1;
long sum;
i=1; //i:正在处理的数组元素,表示前i-1个元素已经满足要求,正处理的是第i个元素
a[1]=1; //为元素a[1]设置初值
while(not_finish){ //not_finish=1:处理没有结束
while(not_finish&&i<=NUM){
for(flag=1,k=1;flag&&k
if(a[k]==a[i])flag=0; //判断第i个元素是否与前i-1个元素重复
for(sum=0,k=1;flag&&k<=i;k++){
sum=10*sum+a[k];
if(sum%k)flag=0; //判断前k位组成的整数是否能被k整除
}
if(!flag){ //flag=0:表示第i位不满足要求,需要重新设置
if(a[i]==a[i-1]){ //若a[i]的值已经经过一圈追上a[i-1]
i--; //i值减1,退回处理前一个元素
if(i>1&&a[i]==NUM)
a[i]=1; //当第i位的值达到NUM时,第i位的值取1
else if(i==1&&a[i]==NUM) //当第1位的值达到NUM时结束
not_finish=0; //置程序结束标记
else a[i]++; //第i位的值取下一个,加1
}
else if(a[i]==NUM) a[i]=1;
else a[i]++;
}
else //第i位已经满足要求,处理第i+1位
if(++i<=NUM) //i+1处理下一元素,当i没有处理完毕时
if(a[i-1]==NUM) a[i]=1; //若i-1的值已为NUM,则a[i]的值为1
else a[i]=a[i-1]+1; //否则,a[i]的初值为a[i-1]值的"下一个"值
}
if(not_finish){
printf("\nThe progressire divisiable number is:");
for(k=1;k<=NUM;k++) //输出计算结果
printf("%d",a[k]);
if(a[NUM-1]
else a[NUM-1]=1;
not_finish=0;
printf("\n");
}
}
}
/*
The progressire divisiable number is:381654729
Press any key to continue
*/
【69.魔术师的猜牌术(1)】
魔术师利用一副牌中的13张黑桃,预先将它们排好后迭在一起,牌面朝下。
对观众说:我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?你们就看。魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,将黑桃A放在桌子上,然后按顺序从上到下数手上的余牌,第二次数1、2,将第一张牌放在这迭牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上,第三次数1、2、3,将前面两张依次放在这迭牌的下面,再翻第三张牌正好是黑桃3。这样依次进行将13张牌全翻出来,准确无误。问魔术师手中的牌原始顺序是怎样安排的?
#include
int a[14];
void main(){
int i,n,j=1; //j:数组(盒子)下标,初始时为1号元素
printf("The original order of cards is:");
for(i=1;i<=13;i++){ //i:要放入盒子中的牌的序号
n=1;
do{
if(j>13) j=1; //由于盒子构成一个圈,j超过最后一个元素则指向1号元素
if(a[j]) j++; //跳过非空的盒子,不进行计数
else{
if(n==i) a[j]=i;
j++;
n++; //对空盒计数,数组下标指向下一个盒子
}
}while(n<=i); //控制空盒计数为i
}
for(i=1;i<=13;i++) //输出牌的排列顺序
printf("%d ",a[i]);
printf("\n");
}
/*
The original order of cards is:1 8 2 5 10 3 12 11 9 4 7 6 13
Press any key to continue
*/
【70.魔术师的猜牌术(2)】
魔术师再次表演,他将红桃和黑桃全部迭在一起,牌面朝下放在手中,对观众说:最上面一张是黑桃A,翻开后放在桌上。以后,从上至下每数两张全依次放在最底下,第三张给观众看,便是黑桃2,放在桌上后再数两张依次放在最底下,第三张给观众看,是黑桃3。如此下去,观众看到放在桌子上牌的顺序是:
黑桃 A 2 3 4 5 6 7 8 9 10 J Q K
红桃 A 2 3 4 5 6 7 8 9 10 J Q K
问魔术师手中牌的原始顺序是什么?
#include
void main(){
int i,n,j = 1;
int a[27] = {0};
a[1] = 1; //初始化第一张牌
printf("The original order of cards is(r:rad b:block):\n");
for(i = 2;i < 27;i++){
n = 1;
do{
if(j > 26){ //j超过最后一个元素就指向第一个元素
j = 1;
}
if(a[j]){ //跳过非空元素不进行计数
j++;
}
else{
if(3 == n){ //数到第三个空盒,将牌放在空盒中
a[j] = i;
}
j++; //对空盒计数,指向下一个盒子
n++;
}
}while(n <= 3); //控制空盒计数为3
}
for(i = 1;i < 27;i++){ //输出牌的排列顺序
printf("%c",a[i] > 13?'r':'b');
printf("%d ",a[i]>13?a[i]-13:a[i]);
}
printf("\n");
}
/*
The original order of cards is(r:rad b:block):
b1 r6 b10 b2 r12 r3 b3 b11 r9 b4 r7 b12 b5 r4 r13 b6 b13 r11 b7 r5 r1 b8 r8 r10
b9 r2
Press any key to continue
*/
【71.约瑟夫问题】
这是17世纪的法国数学家加斯帕在《数目的游戏问题》中讲的一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。
#include
struct node{
int nextp;
int no_out;
}link[31];
void main(){
int i,j,k;
printf("The original circle is(+:pagendom,@:christian):\n");
for(i=1;i<=30;i++){
link[i].nextp=i+1;
link[i].no_out=1;
}
link[30].nextp=1;
j=30;
for(i=0;i<15;i++){
for(k=0;;)
if(k<15){
j=link[j].nextp;
k+=link[j].no_out;
}
else break;
link[j].no_out=0;
}
for(i=1;i<=30;i++)
printf("%c",link[i].no_out? '@':'+');
printf("\n");
}
/*
The original circle is(+:pagendom,@:christian):
+++@@+@+@@@+@+++@@+@@@+++@+@@+
Press any key to continue
*/
【72.邮票组合】
某人有四张3分的邮票和三张5分的邮票,用这些邮票中的一张或若干张可以得到多少种不同的邮资?
#include
int a[27];
void main(){
int i,j,k,s,n=0;
for(i=0;i<=4;i++)
for(j=0;j<=3;j++){
s=i*3+j*5;
for(k=0;a[k];k++)
if(s==a[k])break;
if(!a[k]&&s){
a[k]=s; n++;
}
}
printf("%d kinds:",n);
for(k=0;a[k];k++)
printf("%d ",a[k]);
printf("\n");
}
/*
19 kinds:5 10 15 3 8 13 18 6 11 16 21 9 14 19 24 12 17 22 27
Press any key to continue
*/
【73 和数能表示1~23的5个正整数】
已知五个互不相同的正整数之和为23,且从这五个数中挑选若干个加起来可以表示从1到23之内的全部自然数。问这五个数是什么?
#include
void main(){
int a,b,c,d,e,i,j,k,l,m,x,count=0,f=0;
printf("There are following possble result:\n");
for(a=1;a<=23;a++){
for(b=1+a;b<=23-a;b++)
for(c=1+b;c<=23-a-b;c++)
for(d=1+c;d<=23-a-b-c;d++){
f=1;
if((e=23-a-b-c-d)>d)
for(f=0,x=1;x<24&&!f;x++)
for(f=1,i=0;i<2&&f;i++)
for(j=0;j<2&&f;j++)
for(k=0;k<2&&f;k++)
for(l=0;l<2&&f;l++)
for(m=0;m<2&&f;m++)
if(x==a*i+b*j+c*k+d*l+e*m) f=0;
if(!f)
printf("[%d]: %d %d %d %d %d\n",++count,a,b,c,d,e);
}
}
}
/*
There are following possble result:
[1]: 1 2 3 5 12
[2]: 1 2 3 6 11
[3]: 1 2 3 7 10
[4]: 1 2 4 5 11
[5]: 1 2 4 6 10
[6]: 1 2 4 7 9
Press any key to continue
*/
【74.可称1~40磅的4块砝码】
法国数学家梅齐亚克在他著名的《数字组合游戏》(1962)中提出了一个问题:一位商人有一个重40磅的砝码,一天不小心将砝码摔成了四块。后来商人称得每块的重量都是整磅数,而且发现这四块碎片可以在天平上称1至40磅之间的任意重量。请问这四块碎片各重多少?
#include
#include
void main(){
int weight1,weight2,weight3,weight4,d1,d2,d3,d4,x,flag;
printf("The weight is broke up as following 4 pieces:");
for(weight1=1;weight1<=40;weight1++)
for(weight2=weight1+1;weight2<=40-weight1;weight2++)
for(weight3=weight2+1;weight3<=40-weight1-weight2;weight3++)
if((weight4=40-weight1-weight2-weight3)>=weight3){
for(flag=1,x=1;x<41&&flag;x++)
for(flag=0,d1=1;d1>-2;d1--)
for(d2=1;d2>-2&&!flag;d2--)
for(d3=1;d3>-2&&!flag;d3--)
for(d4=1;d4>-2&&!flag;d4--)
if(x==weight1*d1+weight2*d2+weight3*d3+weight4*d4)
flag=1;
if(flag)
printf("%d %d %d %d\n",weight1,weight2,weight3,weight4);
flag=0;
}
}
/*
The weight is broke up as following 4 pieces:1 3 9 27
Press any key to continue
*/
【75.10个小孩分糖果】
十个小孩围成一圈分糖果,老师分给第一个小孩10块,第二个小孩2块,第三个小孩8块,第四个小孩22块,第五个小孩16块,第六个小孩4块,第七个小孩10块,第八个小孩6块,第九个小孩14块,第十个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块。问经过这样几次后大家手中的糖的块数一样多?每人各有多少块糖?
#include
int j=0;
int judge(int c[]){
int i;
for(i=0;i<10;i++)
if(c[0]!=c[i]) return 1;
return 0;
}
void print(int s[]){
int k;
printf(" %2d ",j++);
for(k=0;k<10;k++) printf("%4d",s[k]);
printf("\n");
}
void main(){
static int sweet[10]={10,2,8,22,16,4,10,6,14,20};
int i,t[10],l;
printf(" child\n");
printf(" round 1 2 3 4 5 6 7 8 9 10\n");
printf(".............................\n");
print(sweet);
while(judge(sweet)){
for(i=0;i<10;i++)
if(sweet[i]%2==0)
t[i]=sweet[i]=sweet[i]/2;
else
t[i]=sweet[i]=(sweet[i]+1)/2;
for(l=0;l<9;l++)
sweet[l+1]=sweet[l+1]+t[l];
sweet[0]+=t[9];
print(sweet);
}
}
/*
child
round 1 2 3 4 5 6 7 8 9 10
.............................
0 10 2 8 22 16 4 10 6 14 20
1 15 6 5 15 19 10 7 8 10 17
2 17 11 6 11 18 15 9 8 9 14
3 16 15 9 9 15 17 13 9 9 12
4 14 16 13 10 13 17 16 12 10 11
5 13 15 15 12 12 16 17 14 11 11
6 13 15 16 14 12 14 17 16 13 12
7 13 15 16 15 13 13 16 17 15 13
8 14 15 16 16 15 14 15 17 17 15
9 15 15 16 16 16 15 15 17 18 17
10 17 16 16 16 16 16 16 17 18 18
11 18 17 16 16 16 16 16 17 18 18
12 18 18 17 16 16 16 16 17 18 18
13 18 18 18 17 16 16 16 17 18 18
14 18 18 18 18 17 16 16 17 18 18
15 18 18 18 18 18 17 16 17 18 18
16 18 18 18 18 18 18 17 17 18 18
17 18 18 18 18 18 18 18 18 18 18
Press any key to continue
*/
【76.小明买书】
小明假期同爸爸一起去书店,他选中了六本书,每本书的单价分别为:3.1,1.7,2,5.3,0.9和7.2。不巧的是,小明的爸爸只带了十几块钱,为了让小明过一个愉快的假期,爸爸扔然同意买书,但提邮购一个要求,要小明从六本书中选出若干本,使得单价相加所得的和同10最接近。你能够帮助小明解决这个问题吗?
#include
#include
void main(){
int d[6],m,i,j;
long b[63],flag;
float c[6],min,x;
printf("Please enter the prices of 6 books:");
for(i=0;i<6;i++) scanf("%f",&c);
for(i=0,min=-1,d[0]=0;d[0]<2;d[0]++)
for(d[1]=0;d[1]<2;d[1]++)
for(d[2]=0;d[2]<2;d[2]++)
for(d[3]=0;d[3]<2;d[3]++)
for(d[4]=0;d[4]<2;d[4]++)
for(d[5]=0;d[5]<2;d[5]++){
for(flag=0,x=0,j=5;j>=0;j--){
x+=c[j]*d[j]; flag=flag*10+d[j];
}
x=((x-10>0)? x-10:10-x);
if(min<0){
min=x;
b[i++]=flag;
}
else if(min-x>1.e-6){
min=x; b[0]=flag; i=1;
}
else if(fabs((double)x-min)<1.e-6)
b[i++]=flag;
}
for(m=0;m
printf("10(+ -)%.2f=",min);
for(flag=b[m],j=0;flag>0;j++,flag/=10)
if(flag%10)
if(flag>1) printf("%.2f+",c[j]);
else printf("%.2f\n",c[j]);
}
}
/*
Please enter the prices of 6 books:3.1 1.7 2.0 5.3 0.9 7.2
10(+ -)2.80=7.20
Press any key to continue
*/
【77.波松瓦酒的分酒趣题】
法国著名数学家波瓦松在表年时代研究过一个有趣的数学问题:某人有12品脱的啤酒一瓶,想从中倒出6品脱,但他没有6品脱的容器,仅有一个8品脱和5品脱的容器,怎样倒才能将啤酒分为两个6品脱呢?
将12品脱酒 8品脱和5品脱的空瓶平分,可以抽象为解不定方程: 8x-5y=6
其意义是:从12品脱的瓶中向8品脱的瓶中倒x次,并且将5品脱瓶中的酒向12品脱的瓶中倒y次,最后在12品脱的瓶中剩余6品脱的酒。
用a,b,c代表12品脱、8品脱和5品脱的瓶子,求出不定方程的整数解,按照不定方程的意义则倒法为: a -> b -> c ->a
x y
倒酒的规则如下:
1) 按a -> b -> c ->a的顺序;
2) b倒空后才能从a中取
3) c装满后才能向a中倒
#include
int i;
void getti(int a,int y,int z) {
int b=0,c=0;
printf(" a%d b%d c%d\n %4d%4d%4d\n",a,y,z,a,b,c);
while(a!=i||b!=i&&c!=i){
if(!b){
a-=y;
b=y;
}
else if(c==z){
a+=z;
c=0;
}
else if(b>z-c){
b-=(z-c);
c=z;
}
else{
c+=b;
b=0;
}
printf(" %4d %4d %4d\n",a,b,c);
}
}
void main(){
int a,y,z;
printf("input Full a,Empty b,c,Get i:");
scanf("%d%d%d%d",&a,&y,&z,&i);
getti(a,y,z);
getti(a,z,y);
}
/*
input Full a,Empty b,c,Get i:6 3 2 2
a6 b3 c2
6 0 0
3 3 0
3 1 2
5 1 0
5 0 1
2 3 1
2 2 2
a6 b2 c3
6 0 0
4 2 0
4 0 2
2 2 2
Press any key to continue
*/
【78.求π的近似值】
请利用“正多边形逼近”的方法求出π的近似值
#include
#include
void main(){
double e=0.1,b=0.5,c,d;
long int i;
for(i=6;;i*=2){
d=1.0-sqrt(1.0-b*b);
b=0.5*sqrt(b*b+d*d);
if(2*i*b-i*e<1e-15)
break;
e=b;
}
printf("pai=%.15lf\n",2*i*b);
printf("The number of edges of required polygon:%ld\n",i);
}
/*
pai=3.141592653589794
The number of edges of required polygon:100663296
Press any key to continue
*/
【79.求π的近似值(2)】
利用随机数法求π的近似值
#include
#include
#include
#define N 30000
void main(){
float x,y;
int c=0,d=0;
randomize();
while(c++<=N) {
x=random(101);
y=random(101);
if(x*x+y*y<=10000)
d++;
}
printf(" pi=%f\n",4. *d/N);
}
【80.奇数平方的一个有趣性质】
编程验证“大于1000的奇数其平方与1的差是8的倍数”。
#include
void main(){
long int a;
for(a=1001;a<=3000;a+=2){
printf("%ld:",a);
printf("(%ld*%ld-1)/8",a,a);
printf("=%ld",(a*a-1)/8);
printf("+%ld\n",(a*a-1)%8);
}
}
【81.角谷猜想】
日本一位中学生发现一个奇妙的“定理”,请角谷教授证明,而教授无能为力,于是产生角谷猜想。猜想的内容是:任给一个自然数,若为偶数除以2,若为奇数则乘3加1,得到一个新的自然数后按照上面的法则继续演算,若干次后得到的结果必然为1。请编程验证。
#include
void main(){
int n,count=0;
printf("Please enter number:");
scanf("%d",&n);
do{
if(n%2){
n=n*3+1;
printf("[%d]:%d*3+1=%d\n",++count,(n-1)/3,n);
}else{
n/=2;
printf("[%d]: %d/2=%d\n",++count,2*n,n);
}
}while(n!=1);
}
/*
Please enter number:12
[1]: 12/2=6
[2]: 6/2=3
[3]:3*3+1=10
[4]: 10/2=5
[5]:5*3+1=16
[6]: 16/2=8
[7]: 8/2=4
[8]: 4/2=2
[9]: 2/2=1
Press any key to continue
*/
【82.四方定理】
数论中著名的“四方定理”讲的是:所有自然数至多只要用四个数的平方和就可以表示。
请编程证此定理。
#include
#include
void main(){
int number,i,j,k,l;
printf("Please enter a number=");
scanf("%d",&number);
for(i=1;i
for(j=0;j<=i;j++)
for(k=0;k<=j;k++)
for(l=0;l<=k;l++)
if(number==i*i+j*j+k*k+l*l){
printf(" %d=%d*%d+%d*%d+%d*%d+%d*%d\n",number,i,i,j,j,k,k,l,l);
exit(0);
}
}
/*
Please enter a number=23
23=3*3+3*3+2*2+1*1
Press any key to continue
*/
【83.卡布列克常数】
验证卡布列克运算。任意一个四位数,只要它们各个位上的数字是不全相同的,就有这样的规律:
1)将组成该四位数的四个数字由大到小排列,形成由这四个数字构成的最大的四位数;
2)将组成该四位数的四个数字由小到大排列,形成由这四个数字构成的最小的四位数(如果四个数中含有0,则得到的数不足四位);
3)求两个数的差,得到一个新的四位数(高位零保留)。
重复以上过程,最后得到的结果是6174,这个数被称为卡布列克数。
#include
int count=0;
void parse_sort(int num,int *each){
int i,*j,*k,temp;
for(i=0;i<=4;i++){
j=each+3-i;
*j=num%10;
num/=10;
}
for(i=0;i<3;i++)
for(j=each,k=each+1;j
if(*j>*k) {
temp=*j;
*j=*k;
*k=temp;
}
return;
}
void max_min(int *each,int *max,int *min) {
int *i;
*min=0;
for(i=each;i
*min=*min*10+*i;
*max=0;
for(i=each+3;i>=each;i--)
*max=*max*10+*i;
return;
}
void vr6174(int num){
int each[4],max,min;
if(num!=6174&&num){
parse_sort(num,each);
max_min(each,&max,&min);
num=max-min;
printf("[%d]: %d-%d=%d\n",++count,max,min,num);
vr6174(num);
}
}
void main(){
int n;
printf("Enter a number:");
scanf("%d", &n);
vr6174(n);
}
/*
Enter a number:1234
[1]: 4321-1234=3087
[2]: 8730-378=8352
[3]: 8532-2358=6174
Press any key to continue
*/
【84.尼科彻斯定理】
验证尼科彻斯定理,即:任何一个整数的立方都可以写成一串连续奇数的和。
#include
void main(){
int a,b,c,d;
printf("Please enter a number:");
scanf("%d",&a);
b=a*a*a;
printf("%d*%d*%d=%d=",a,a,a,b);
for(d=0,c=0;c
d+=a*a-a+1+c*2;
printf(c?"+%d":"%d",a*a-a+1+c*2);
}
if(d==b)printf(" Y\n");
else printf(" N\n");
}
/*
Please enter a number:12
12*12*12=1728=133+135+137+139+141+143+145+147+149+151+153+155 Y
Press any key to continue
*/
【85.回文数的形成】
任取一个十进制整数,将其倒过来后与原来的整数相加,得到一个新的整数后重复以上步聚,则最终可得到一个回文数。请编程验证。
#include
#define MAX 2147483647
long re(long int a) {
long int t;
for(t=0;a>0;a/=10)
t=t*10+a%10;
return t;
}
int nonres(long int s) {
if(re(s)==s) return 1;
else return 0;
}
void main(){
long int n,m;
int count=0;
printf("Please enetr a number optionaly:");
scanf("%ld",&n);
printf("The generation process of palindrome:\n");
while(!nonres((m=re(n))+n)){
if(m+n>=MAX){
printf(" input error,break.\n");
break;
}else{
printf("[%d]:%ld+%ld=%ld\n",++count,n,m,m+n);
n+=m;
}
}
printf("[%d]:%ld+%ld=%ld\n",++count,n,m,m+n);
printf("Here we reached the aim at last!\n");
}
/*
Please enetr a number optionaly:425
The generation process of palindrome:
[1]:425+524=949
Here we reached the aim at last!
Press any key to continue
*/
【86.自动发牌】
一副扑克有52张牌,打桥牌时应将牌分给四个人。请设计一个程序完成自动发牌的工作。要求:黑桃用S(Spaces)表示;红桃用H(Hearts)表示;方块用D(Diamonds)表示;梅花用C(Clubs)表示。
按照打桥牌的规定,每人应当有13张牌。在人工发牌时,先进行洗牌,然后将洗好的牌按一定的顺序发给每一个人。为了便于计算机模拟,可将人工方式的发牌过程加以修改:先确定好发牌顺序:1、2、3、4;将52张牌顺序编号:黑桃2对应数字0,红桃2对应数字1,方块2对应数字2,梅花2对应数字3,黑桃3对应数字4,红桃3对应数字5,...然后从52 张牌中随机的为每个人抽牌。
#include
#include
#include
void p(int *, char *);
int comp(const void *j, const void *i);
int main(){
static char n[] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};
int a[53], b1[13], b2[13], b3[13], b4[13];
int b11 = 0, b22 = 0, b33 = 0, b44 = 0, t = 1, m, flag, i;
srand((unsigned)time(NULL));
while (t <= 52) { //控制发52张牌
m = rand() % 52; //产生0~51之间的随机数
for (flag = 1, i = 1; i <= t && flag; i++) { //查找新产生的随机数是否已经存在
if (m == a[i]) {
flag = 0;
}
}
if (flag) {
a[t++] = m;
if (0 == t % 4) //根据t的模值,判断当前的牌
{ //应存入哪个数组中
b1[b11++] = a[t - 1];
}
else {
if (1 == t % 4) {
b2[b22++] = a[t - 1];
}
else {
if (2 == t % 4) {
b3[b33++] = a[t - 1];
}
else {
if (3 == t % 4) {
b4[b44++] = a[t - 1];
}
}
}
}
}
}
qsort(b1, 13, sizeof(b1[0]), comp); //将每个人的牌进行排序
qsort(b2, 13, sizeof(b2[0]), comp);
qsort(b3, 13, sizeof(b3[0]), comp);
qsort(b4, 13, sizeof(b4[0]), comp);
printf("No.1"); //分别打印每个人的牌
p(b1, n);
printf("\nNo.2");
p(b2, n);
printf("\nNo.3");
p(b3, n);
printf("\nNo.4");
p(b4, n);
printf("\n");
return 0;
}
void p(int *b, char *n) {
int i;
printf("\n%c ", 'S');
for (i = 0; i < 13; i++) {
if (0 == b[i] / 13) {
printf("%c", n[b[i] % 13]);
}
}
printf("\n%c ", 'H');
for (i = 0; i < 13; i++) {
if (1 == b[i] / 13) {
printf("%c", n[b[i] % 13]);
}
}
printf("\n%c ", 'D');
for (i = 0; i < 13; i++) {
if (2 == b[i] / 13) {
printf("%c", n[b[i] % 13]);
}
}
printf("\n%c ", 'C');
for (i = 0; i < 13; i++) {
if (3 == b[i] / 13 || 4 == b[i] / 13) {
printf("%c", n[b[i] % 13]);
}
}
}
int comp(const void *j, const void *i) {
return(*(char *)i - *(char *)j);
}
/*
No.1
S AT
H A9643
D QJ7
C 943
No.2
S KJ97
H T
D K86542
C 65
No.3
S 853
H Q52
D T3
C AKT87
No.4
S Q642
H KJ87
D A9
C QJ2
Press any key to continue
*/
【87.黑白子交换】
有三个白子和三个黑子如下图布置:
○ ○ ○ . ● ● ●
游戏的目的是用最少的步数将上图中白子和黑子的位置进行交换:
● ● ● . ○ ○ ○
游戏的规则是:(1)一次只能移动一个棋子; (2)棋子可以向空格中移动,也可以跳过一个对方的棋子进入空格,但不能向后跳,也不能跳过两个子。请用计算机实现上述游戏。
分析本题,先用人来解决问题,可总结出以下规则:
(1) 黑子向左跳过白子落入空格,转(5)
(2) 白子向右跳过黑子落入空格,转(5)
(3) 黑子向左移动一格落入空格(但不应产生棋子阻塞现象),转(5)
(4) 白子向右移动一格落入空格(但不应产生棋子阻塞现萌),转(5)
(5) 判断游戏是否结束,若没有结束,则转(1)继续。
所谓的“阻塞”现象就是:在移动棋子的过程中,两个尚未到位的同色棋子连接在一起,使棋盘中的其它棋子无法继续移动。例如按下列方法移动棋子:
0
○ ○ ○ . ● ● ●
1 ○ ○ . ○ ● ● ●
2 △ ○ ○ ● ○ . ● ●
3
○ ○ ● . ○ ● ●
4 两个●连在一起产生阻塞
○ ○ ● ● ○ . ●
或4 两个白连在一起产生阻塞
○ . ● ○ ○ ● ●
产生阻塞的现象的原因是在第2步(△状态)时,棋子○不能向右移动,只能将●向左移动。
总结产生阻塞的原因,当棋盘出现“黑、白、空、黑”或“白、空、黑、白”状态时,不能向左或向右移动中间的棋子,只移动两边的棋子。
按照上述规则,可以保证在移动棋子的过程中,不会出现棋子无法移动的现象,且可以用最少的步数完成白子和黑子的位置交换。
#include
#include
using namespace std;
#define WHITEPIECE 1
#define BLACKPIECE 2
#define NULLVALUE 0
#define MAPLEN 7
typedef struct stStatus{
int m_data[MAPLEN];
}Status;
list g_listatus; //存储整个步骤
void GameStep(Status& st, int NullPos);
bool GameOver(Status& st);
int main(){
Status ss = {1,1,1,0,2,2,2};
GameStep(ss,3);
return 0;
}
void GameStep(Status& st, int NullPos){
g_listatus.push_back(st);
if(GameOver(st)){
list::iterator it = g_listatus.begin();
for(;it != g_listatus.end();++it){
for(int i=0; i
cout << it->m_data[i] << " ";
}
cout << endl;
}
return;
}
if((NullPos+1) < MAPLEN){ //空格的右边第一个棋子判别
if(st.m_data[NullPos+1] == BLACKPIECE){
if((NullPos < 3)||(NullPos-1)>-1 && (st.m_data[NullPos-1] != BLACKPIECE)){
st.m_data[NullPos] = BLACKPIECE;
st.m_data[NullPos+1] = NULLVALUE;
GameStep(st, NullPos+1);
}
}
}
if((NullPos+2) < MAPLEN){ //空格的右边第二个棋子判别
if(st.m_data[NullPos+2] == BLACKPIECE){
if((NullPos < 3)||(NullPos-1)>-1 && (st.m_data[NullPos+1] != BLACKPIECE) && (st.m_data[NullPos-1] != BLACKPIECE)){
st.m_data[NullPos] = BLACKPIECE;
st.m_data[NullPos+2] = NULLVALUE;
GameStep(st, NullPos+2);
}
}
}
if((NullPos-1) > -1){ //空格的左边第一个棋子判别
if(st.m_data[NullPos-1] == WHITEPIECE){
if((NullPos > 3)||(NullPos+1) < MAPLEN && (st.m_data[NullPos+1] != WHITEPIECE)){
st.m_data[NullPos] = WHITEPIECE;
st.m_data[NullPos-1] = NULLVALUE;
GameStep(st, NullPos-1);
}
}
}
if((NullPos-2) > -1){ //空格的左边第二个棋子判别
if(st.m_data[NullPos-2] == WHITEPIECE){
if((NullPos > 3)||(NullPos+1) < MAPLEN && (st.m_data[NullPos+1] != WHITEPIECE) && (st.m_data[NullPos-1] != WHITEPIECE)){
st.m_data[NullPos] = WHITEPIECE;
st.m_data[NullPos-2] = NULLVALUE;
GameStep(st, NullPos-2);
}
}
}
g_listatus.pop_back();
st = g_listatus.back();
return;
}
bool GameOver(Status& st){
if(st.m_data[3] == NULLVALUE){
return (st.m_data[0] + st.m_data[1] + st.m_data[2] == 6) ? true : false;
}
return false;
}
/*
1 1 1 0 2 2 2
1 1 1 2 0 2 2
1 1 0 2 1 2 2
1 0 1 2 1 2 2
1 2 1 0 1 2 2
1 2 1 2 1 0 2
1 2 1 2 1 2 0
1 2 1 2 0 2 1
1 2 0 2 1 2 1
0 2 1 2 1 2 1
2 0 1 2 1 2 1
2 2 1 0 1 2 1
2 2 1 2 1 0 1
2 2 1 2 0 1 1
2 2 0 2 1 1 1
2 2 2 0 1 1 1
Press any key to continue
*/
【88.常胜将军】
现有21根火柴,两人轮流取,每人每次可以取走1至4根,不可多取,也不能不取,谁取最后一楰火柴谁输。请编写一个程序进行人机对弈,要求人先取,计算机后取;计算机一方为“常胜将军”。
#include
void main(){
int a=21,i;
printf("Game begin:\\n");
while(a>0){
do{
printf("How many stick do you wish to take(1~%d)?",a>4?4:a);
scanf("%d",&i);
}while(i>4||i<1||i>a);
if(a-i>0) printf(" %d stick left in the pile.\n",a-i);
if((a-i)<=0){
printf(" You have taken the last stick.\n");
printf(" * * * You lose! \nGame Over.\n");
break;
}
else
printf(" Compute take %d stick.\n",5-i);
a-=5;
printf(" %d stick left in the pile.\n",a);
}
}
【89.抢 30】
这是中国民间的一个游戏。两人从1开始轮流报数,每人每次可报一个数或两个连续的数,谁先报到30,谁就为胜方。
#include
#include
#include
int input(int t);
int copu(int s);
int main(){
int tol=0;
printf("\n* * * * * * * *catch thirty* * * * * * * \n");
printf("Game Begin\n");
rand(); //初始化随机数发生器
//取随机数决定机器人和人谁想走第一步。若为1,则表示人先走第一步
if(rand()%2)
tol=input(tol);
while(tol!=30) //游戏结束条件
if((tol=copu(tol))==30) //计算机取一个数,若为30则机器胜利
printf("I lose! \n");
else
if((tol=input(tol))==30) //人取一个数,若为30则人胜利
printf("I lose! \n");
printf(" * * * * * * * *Game Over * * * * * * * *\n");
return 0;
}
int input(int t){
int a;
do{
printf("Please count:");
scanf("%d",&a);
if(a>2||a<1||t+a>30)
printf("Error input,again!");
else
printf("You count:%d\n",t+a);
}while(a>2||a<1||t+a>30);
return t+a; //返回当前已经取走的数的累加和
}
int copu(int s){
int c;
printf("Computer count:");
if((s+1)%3==0) //若剩余的数的模为1,则取1
printf(" %d\n",++s);
else if((s+2)%3==0) {
s+=2; //若剩余的数的模为2,则取2
printf(" %d\n",s);
}
else{
c=rand()%2+1; //否则随机取1或2
s+=c;
printf(" %d\n",s);
}
return s;
}
/*
* * * * * * * *catch thirty* * * * * * *
Game Begin
Please count:1
You count:1
Computer count: 3
Please count:4
Error input,again!Please count:2
You count:5
Computer count: 6
Please count:1
You count:7
Computer count: 9
Please count:2
You count:11
Computer count: 12
Please count:2
You count:14
Computer count: 15
Please count:2
You count:17
Computer count: 18
Please count:2
You count:20
Computer count: 21
Please count:2
You count:23
Computer count: 24
Please count:2
You count:26
Computer count: 27
Please count:2
You count:29
Computer count: 30
I lose!
* * * * * * * *Game Over * * * * * * * *
Press any key to continue
*/
【90.搬山游戏】
设有n座山,计算机与人为比赛的双方,轮流搬山。规定每次搬山的数止不能超 过k座,谁搬最后一座谁输。游戏开始时。计算机请人输入山的总数(n)和每次允许搬山的最大数止(k)。然后请人开始,等人输入了需要搬走的山的数目后,计算机马上打印出它搬多少座山,并提示尚余多少座山。双方轮流搬山直到最后一座山搬完为止。计算机会显示谁是赢家,并问人是否要继续比赛。若人不想玩了,计算机便会统计出共玩了几局,双方胜负如何。
计算机参加游戏时应遵循下列原则:
1) 当:剩余山数目-1<=可移动的最大数k 时计算机要移(剩余山数目-1)座,以便将最后一座山留给人。
2)对于任意正整数x,y,一定有: 0<=x%(y+1)<=y
在有n座山的情况下,计算机为了将最后一座山留给人,而且又要控制每次搬山的数目不超过最大数k,它应搬山的数目要满足下列关系: (n-1)%(k+1)
如果算出结果为0,即整除无余数,则规定只搬1座山,以防止冒进后发生问题。
#include
void main(){
int n,k,x,y,cc,pc,g;
printf("More Mountain Game\\n");
printf("Game Begin\n");
pc=cc=0;
g=1;
for(;;){
printf("No.%2d game \n",g++);
printf("---------------------------------------\n");
printf("How many mpuntains are there?");
scanf("%d",&n);
if(!n) break;
printf("How many mountains are allowed to each time?");
do{
scanf("%d",&k);
if(k>n||k<1) printf("Repeat again!\n");
}while(k>n||k<1);
do{
printf("How many mountains do you wish movw away?");
scanf("%d",&x);
if(x<1||x>k||x>n){
printf("IIIegal,again please!\n");
continue;
}
n-=x;
printf("There are %d mountains left now.\n",n);
if(!n){
printf("...............I win. You are failure...............\n\n");cc++;
}
else{
y=(n-1)%(k+1);
if(!y) y=1;
n-=y;
printf("Copmputer move %d mountains away.\n",y);
if(n) printf(" There are %d mountains left now.\n",n);
else{
printf("...............I am failure. You win..................\n\n");
pc++;
}
}
}while(n);
}
printf("Games in total have been played %d.\n",cc+pc);
printf("You score is win %d,lose %d.\n",pc,cc);
printf("My score is win %d,lose %d.\n",cc,pc);
}
【91.人机猜数游戏】
由计算机“想”一个四位数,请人猜这个四位数是多少。人输入四位数字后,计算机首先判断这四位数字中有几位是猜对了,并且在对的数字中又有几位位置也是对的,将结果显示出来,给人以提示,请人再猜,直到人猜出计算机所想的四位数是多少为止。
例如:计算机“想”了一个“1234”请人猜,可能的提示如下:
人猜的整数 计算机判断有几个数字正确 有几个位置正确
1122 2 1
3344 2 1
3312 3 0
4123 4 0
1243 4 2
1234 4 4
游戏结束
请编程实现该游戏。游戏结束时,显示人猜一个数用了几次。
#include
#include
#include
#include
void main(){
int stime,a,z,t,i,c,m,g,s,j,k,l[4];
long ltime;
ltime=time(NULL);
stime=(unsigned int)ltime/2;
srand(stime);
z=rand()%9999;
printf("I have a number with 4 digits in mind,please guess.\n");
for(c=1;;c++){
printf("Enter a number with 4 digits:");
scanf("%d",&g);
a=z;j=0;k=0;l[0]=l[1]=l[2]=l[3]=0;
for(i=1;i<5;i++){
s=g;m=1;
for(t=1;t<5;t++){
if(a%10==s%10){
if(m&&t!=l[0]&&t!=l[1]&&t!=l[2]&&t!=l[3]){
j++;
m=0;
l[j-1]=t;
}
if(i==t) k++;
}
s/=10;
}
a/=10;
}
printf("You hane correctly guessed %d digits,\n",j);
printf("and correctly guessed %d digits in exact position.\n",k);
if(k==4) break;
}
printf("Now you have correctly guessed the whole number after %d times.\n",c);
}
【92.人机猜数游戏(2)】
将以上游戏双方倒一下,请人想一个四位的整数,计算机来猜,人给计算机提示信息,最终看计算机用几次猜出一个人“想”的数。请编程实现。
基于对问题的分析和理解,将问题进行简化,求解分为两个步聚来完成:首先确定四位数字的组成,然后再确定四位数字的排列顺序。可以列出如下规则:
1)分别显示四个1,四个2,......,四个0,确定四位数字的组成。
2)依次产生四位数字的全部排列(依次两两交换全部数字的位置)。
3)根据人输入的正确数字及正确位置的数目,进行分别处理:
(注意此时不出现输入的情况,因为在四个数字已经确定的情况下,若有3个位置正确,则第四个数字的位置必然也是正确的)
若输入4:游戏结束。
判断本次输入与上次输入的差值
若差为2:说明前一次输入的一定为0,本次输入的为2,本次交换的两个数字的位置是正确的,只要交换另外两个没有交换过的数字即可结束游戏。
若差为-2:说明前一次输入的一定为2,本次的一定为0。说明刚交换过的两个数字的位置是错误的,只要将交换的两个数字位置还原,并交换另外两个没有交换过的数字即可结束游戏。
否则:若本次输入的正确位置数<=上次的正确位置数
则恢复上次四位数字的排列,控制转3)
否则:将本次输入的正确位置数作为“上次输入的正确位置数”,控制转3)。
#include
#include
#include
int *dict = NULL;
void dict_gen(){
int a, b, c, d;
int index;
if(dict != NULL){
free(dict);
}
dict = malloc(sizeof(int) * 10 * 9 * 8 * 7);
index = 0;
for(a=0; a<10; a++){
for(b=0; b<10; b++){
if(b == a) continue;
for(c=0; c<10; c++){
if(c == a || c == b) continue;
for(d=0; d<10; d++) {
if(d==a || d==b || d==c) continue;
dict[index] = a << 24 | b << 16 | c << 8 | d;
index++;
}
}
}
}
}
int check(int guess, int dst){
int A, B;
int i;
int j;
int t;
A = 0;
B = 0;
for(i=0; i<4; i++){
t = (guess >> (24-i*8)) & 0xff;
for(j=0; j<4; j++) {
if( ((dst>>(24-j*8)) & 0xff) == t ){
B++;
}
}
if( t == ((dst>>(24-i*8)) & 0xff) ){
A++;
}
}
B -= A;
return A*10+B;
}
int main(){
char buffer[1024];
int index;
int A, B;
int i;
int count;
int times;
dict_gen();
index = 0;
times = 0;
while(1){
while(dict[index] == 0){
index ++;
}
printf("%d%d%d%d/n", (dict[index]>>24) & 0xff, (dict[index]>>16) & 0xff, (dict[index]>>8) & 0xff,(dict[index]) & 0xff);
fflush(stdout);
times ++;
if(fgets(buffer, 1024, stdin) == NULL){
return -1;
}
buffer[5] = '/0';
A = buffer[0] - '0';
B = buffer[2] - '0';
if(A == 4){
printf("/nSuccess. guess %d times./n", times);
fflush(stdout);
return 0;
}
count = 0;
for(i=index+1; i<10*9*8*7; i++){
if(check(dict[index], dict[i]) != A*10+B){
dict[i] = 0;
}
if(dict[i] != 0){
count ++;
}
}
dict[index] = 0;
}
return 0;
}
【93.汉诺塔】
约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
这是一个著名的问题,几乎所有的教材上都有这个问题。由于条件是一次只能移动一个盘,且不允许大盘放在小盘上面,所以64个盘的移动次数是:
18,446,744,073,709,551,615
这是一个天文数字,若每一微秒可能计算(并不输出)一次移动,那么也需要几乎一百万年。我们仅能找出问题的解决方法并解决较小N值时的汉诺塔,但很难用计算机解决64层的汉诺塔。
分析问题,找出移动盘子的正确算法。
首先考虑a杆下面的盘子而非杆上最上面的盘子,于是任务变成了:
*将上面的63个盘子移到b杆上;
*将a杆上剩下的盘子移到c杆上;
*将b杆上的全部盘子移到c杆上。
将这个过程继续下去,就是要先完成移动63个盘子、62个盘子、61个盘子....的工作。
为了更清楚地描述算法,可以定义一个函数movedisc(n,a,b,c)。该函数的功能是:将N个盘子从A杆上借助C杆移动到B杆上。这样移动N个盘子的工作就可以按照以下过程进行:
1) movedisc(n-1,a,c,b);
2) 将一个盘子从a移动到b上;
3) movedisc(n-1,c,b,a);
重复以上过程,直到将全部的盘子移动到位时为止。
#include
void movedisc(unsigned n,char fromneedle,char toneedle,char usingneedle);
int i=0;
void main()
{
unsigned n;
printf("please enter the number of disc:");
scanf("%d",&n);
printf("\tneedle:\ta\t b\t c\n");
movedisc(n,'a','c','b');
printf("\t Total: %d\n",i);
}
void movedisc(unsigned n,char fromneedle,char toneedle,char usingneedle){
if(n>0) {
movedisc(n-1,fromneedle,usingneedle,toneedle);
++i;
tch(fromneedle) {
case 'a':tch(toneedle) {
case 'b': printf("\t[%d]:\t%2d.........>%2d\n",i,n,n);
break;
case 'c': printf("\t[%d]:\t%2d...............>%2d\n",i,n,n);
break;
}
break;
case 'b':tch(toneedle) {
case 'a': printf("\t[%d]:\t%2d<...............>%2d\n",i,n,n);
break;
case 'c': printf("\t[%d]:\t %2d........>%2d\n",i,n,n);
break;
}
break;
case 'c':tch(toneedle) {
case 'a': printf("\t[%d]:\t%2d<............%2d\n",i,n,n);
break;
case 'b': printf("\t[%d]:\t%2d<........%2d\n",i,n,n);
break;
}
break;
}
movedisc(n-1,usingneedle,toneedle,fromneedle);
}
}
【94.兎子产子】
从前有一对长寿兎子,它们每一个月生一对兎子,新生的小兎子两个月就长大了,在第二个月的月底开始生它们的下一代小兎子,这样一代一代生下去,求解兎子增长数量的数列。
#include
void main(){
int n,i,un1,un2,un;
for(n=2;n<3;) {
printf("Please enter required number of generation:");
scanf("%d",&n);
if(n<3) printf("\n Enter error!\n");
}
un=un2=1;
printf("The repid increase of rabbits in first %d generation is as felow:\n",n);
printf("l\tl\t");
for(i=3;i<=n;i++){
un1=un2;
un2=un;
un=un1+un2;
printf(i%10?"%d\t":"%d\n",un);
}
printf("\n");
}
/*
Please enter required number of generation:10
The repid increase of rabbits in first 10 generation is as felow:
l l 2 3 5 8 13 21 34 55
Press any key to continue
*/
【95.将阿拉伯数字转换为罗马数字】
将大于0小于1000的阿拉伯数字转换为罗马数字。
#include
void main(){
static char *a[][10]={"","I","II","III","IV","V","VI","VII","VIII","IX"
"","X","XX","XXX","XL","L","LX","LXX","LXXX","XCC",
"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"
};
int n,t,i,m;
printf("Please enter number:");
scanf("%d",&n);
printf("%d=",n);
for(m=0,i=1000;m<3;m++,i/=10){
t=(n%i)/(i/10);
printf("%s",a[2-m][t]);
}
printf("\n");
}
/*
Please enter number:333
333=CDXLIII
Press any key to continue
*/
【96.选美比赛】
在选美大奖赛的半决胜赛现场,有一批选手参加比赛,比赛的规则是最后得分越高,名次越低。当半决决赛结束时,要在现场按照选手的出场顺序宣布最后得分和最 后名次,获得相同分数的选手具有相同的名次,名次连续编号,不用考虑同名次的选手人数。例如:
选手序号: 1,2,3,4,5,6,7
选手得分: 5,3,4,7,3,5,6
则输出名次为: 3,1,2,5,1,3,4
请编程帮助大奖赛组委会完成半决赛的评分和排名工作。
#include
#define NUM 7 /*定义要处理的人数*/
int a[NUM+1]={0,5,3,4,7,3,5,6}; /*为简单直接定义选手的分数*/
int m[NUM+1],l[NUM+1]; /*m:已编名次的标记数组 l:记录同名次元素的下标*/
int main()
{
int i,smallest,num,k,j;
num=1; /*名次*/
for(i=1;i<=NUM;i++) /*控制扫描整个数组,每次处理一个名次*/
if(m[i]==0) /*若尚未进行名次处理(即找到第一个尚未处理的元素)*/
{
smallest=a[i]; /*取第一个未处理的元素作为当前的最小值*/
k=1; /*数组l的下标,同名次的人数*/
l[k]=i; /*记录分值为smallest的同名次元素的下标*/
for(j=i+1;j<=NUM;j++) /*从下一个元素开始对余下的元素进行处理*/
if(m[j]==0) /*若为尚未进行处理的元素*/
if(a[j]
{
smallest=a[j]; /*则重新设置当覵最小值*/
k=0; /*重新设置同名次人数*/
l[++k]=j; /*重新记录同名次元素下标*/
}
else if(a[j]==smallest) /*若与当前最低分相同*/
l[++k]=j; /*记录同名次的元素下标*/
for(j=1;j<=k;j++) /*对同名次的元素进行名次处理*/
m[l][j]=num;
num++; /*名次加1*/
i=0; /*控制重新开始,找下一个没排名次的元素*/
}
printf("Player-No score Rank ");
for(j=1;j<=NUM;j++) /*控制输出*/
printf(" %3d %4d %4d ",j,a[j],m[j]);
}
【97.满足特异条件的数列】
输入m和n(20>=m>=n>0)求出满足以下方程的正整数数列 i1,i2,...,in,使得:i1+i1+...+in=m,且i1>=i2...>=in。例如:
当n=4, m=8时,将得到如下5 个数列:
5 1 1 1 4 2 1 1 3 3 1 1 3 2 2 1 2 2 2 2
#include
#define NUM 10
int i[NUM];
void main(){
int sum,n,total,k,flag,count=0;
printf("Please enter requried terms(<=10):");
scanf("%d",&n);
printf(" their sum:");
scanf("%d",&total);
sum=0;
k=n;
i[n]=1;
printf("There are following possible series:\n");
while(1) {
if(sum+i[k]
if(k<=1){
i[1]=total-sum;
flag=1;
}
else{
sum+=i[k--];
i[k]=i[k+1];
continue;
}
else if(sum+i[k]>total||k!=1){
sum-=i[++k];
flag=0;
}
else flag=1;
if(flag){
printf("[%d]:",++count);
for(flag=1;flag<=n;++flag)
printf("%d",i[flag]);
printf("\n");
}
if(++k>n)
break;
sum-=i[k];
i[k]++;
}
}
/*
Please enter requried terms(<=10):4
their sum:8
There are following possible series:
[1]:5111
[2]:4211
[3]:3311
[4]:3221
[5]:2222
Press any key to continue
*/
【98. 八皇后问题】
在一个8×8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。问 共有多少种不同的方法。
#include
#define NUM 8 //定义数组的大小
int a[NUM+1];
int main(){
int i,k,flag,not_finish=1,count=0;
i=1; //正在处理的元素下标,表示前i-1个元素已符合要求,正在处理第i个元素
a[1]=1; //为数组的第一个元素赋初值
printf("The possible configuration of 8 queens are: ");
while(not_finish) { //not_finish=1:处理尚未结束
while(not_finish&&i<=NUM) { //处理尚未结束且还没处理到第NUM个元素
for(flag=1,k=1;flag&&k
if(a[k]==a[i])flag=0;
for(k=1;flag&&k
if((a[i]==a[k]-(k-i))||(a[i]==a[k]+(k-i))) flag=0;
if(!flag) { //若存在矛盾不满足要求,需要重新设置第i个元素
if(a[i]==a[i-1]){ //若a[i]的值已经经过一圈追上a[i-1]的值
i--; //退回一步,重新试探处理前一个元素
if(i>1&&a[i]==NUM)
a[i]=1; //当a[i]为NUM时将a[i]的值置1
else if(i==1&&a[i]==NUM)
not_finish=0; //当第一位的值达到NUM时结束
else
a[i]++; //将a[i]的值取下一个值
}
else if(a[i]==NUM) a[i]=1;
else a[i]++; //将a[i]的值取下一个值
}
else if(++i<=NUM)
if(a[i-1]==NUM) a[i]=1; //若前一个元素的值为NUM则a[i]=1
else a[i]=a[i-1]+1; //否则元素的值为前一个元素的下一个值
}
if(not_finish){
++count;
printf((count-1)%3?" [%2d]: ":" [%2d]: ",count);
for(k=1;k<=NUM;k++) //输出结果
printf(" %d",a[k]);
if(a[NUM-1]
else a[NUM-1]=1;
i=NUM-1; //开始寻找下一个足条件的解
}
}
}
【99.超长正整数的加法】
请设计一个算法来完成两个超长正整数的加法。
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
//freopen("1.txt","r",stdin);
char ss[512];
string s;
string s1,s2;
int i,j,len1,len2,lmax;
while(cin>>s1>>s2) {
len1=s1.length();
len2=s2.length();
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
lmax=len1>len2?len1:len2;
int temp=0;
int sum[512];
int k=0,j;
for(i=0; i
int a=0,b=0;
if(i
a=s1[i]-'0';
else
a=0;
if(i
b=s2[i]-'0';
else
b=0;
int result=a+b+temp;
temp=result>9?1:0;
sum[k++]=result%10;
}
if(temp>0) {
sum[k]=1;
for(j=k; j>=0; j--)
cout<
}
else{
for(j=k-1; j>=0; j--)
cout<
}
cout<
}
return 0;
}
【100. 数字移动】
0--------0----------0
| \\ | / |
0--------0----------0
| / | \\ |
0--------0----------0
在图中的九个点上,空出中间的点,其余的点上任意填入数字1到8;1的位置固定不动,然后移动其余的数字,使1到8顺时针从小到大排列.移动的规律是:只 能将数字沿线移向空白的点.请编程显示数字移动过程。
#include
using namespace std;
const int MAX = 9;
int a[MAX]={0,1,2,5,8,7,6,3}; //指针数组.依次存入矩阵中构成环的元素下标
int b[MAX]; //表示3X3矩阵,b[4]为空格
int c[MAX]; //确定1所在的位置后,对环进行调整的指针数组
int counter = 0; //数字移动计数器
void print();//输出矩阵
int main(){
freopen("data.txt", "r", stdin);
int i, j, k, t;
for(i = 0; i < 8; i++)
cin >> b[a[i]];
print();
for(t = -1, j = 0; j < 8 && t == -1; j++)//找出1的位置,用t记录下来
if(b[a[j]] == 1)
t = j;
for(j = 0; j < 8; j++)//将环形矩阵的各个元素位置调整到以1为首,方便进行排序
c[j] = a[(j+t)%8];
for(i = 2; i < 9; i++)//按2到8的顺序,依次把对应位的数字找到并移动
for(j = i - 1; j < 8; j++)//找到对应i
if(b[c[j]] == i && j != i -1) {
b[4] = i;
b[c[j]] = 0;
print();
for(k = j; k != i-1; k--){//把i后面的数字往后移动
b[c[k]] = b[c[k-1]];
b[c[k-1]] = 0;
print();
}
b[c[k]] = i;
b[4] = 0;
print();
break;
}
else if(b[c[j]] == i) break;//对应位置的数字匹配,直接跳到下一个i
return 0;
}
void print(){
for(int i = 0; i < 9;) {
for(int j = i; i < j + 3; i++)//控制输出每行的三个数字
cout << b[i] << "\t";
cout << endl;
}
cout << "--------" << counter++ << "--------" << endl;
}