信息学竞赛复习1.斐波拉契数列(1000000以内的数字)
#include “stdio.h”
#include “stdlib.h”
void main()
{
long fib1=1,fib2=1,fib=0;
printf("1000000以内的数字:\n\n");
printf("%d\n%d\n",fib1,fib2);
while (fib<1000000)
{
fib=fib1+fib2;
fib1=fib2;
fib2=fib;
printf( "%d \n", fib);
}
system("pause");
}
2.约瑟夫问题
(1)约瑟夫问题_数组
#include "stdio.h"
#include "stdlib.h"
#define Length 100
void main()
{
int i,j;
int len; //输入的总节点数
int n,m; //输入的每次数几个
int remain; //剩下的节点数
int current; //当前数到那个数字
int a[Length];
for(i=0;i { a[i]=1; } printf("请输入约瑟夫问题节点总数:"); len=41; //scanf("%d",&len); printf("请输入每次数的节点数字:"); n=3; //scanf("%d",&n); remain=len; //剩下的节点数 current=0; //当前数到那个数字 m=0; //计数到n,m=n时清零 //从1开始数 //循环到剩下的节点数为0 printf("出列的节点的编号依次为:"); while(remain>0) { current++; while(current>len) { current-=len; } if(a[current]==1) { m++; if(m==n) { a[current]=0; remain--; printf("%d, ",current); m=0; } } } system("pause"); } (2)约瑟夫问题_数组环 #include "stdio.h" #include "stdlib.h" void main() { int a[100]; int i,len,n; //i循环 len总数 n每次数几个 int cur,m,remain; //cur当前是哪个 m 计数 remain 剩下几个//int t1,t2; for(i=0;i<100;i++) { a[i]=i+1; } printf("请输入约瑟夫问题节点总数:"); len=41; //scanf("%d",&len); printf("请输入每次数的节点数字:"); n=3; //scanf("%d",&n); a[len]=1; //首尾相连 remain=len; //开始前,剩余数为总数 cur=1; //当前从第1个开始 m=1; //计数从1开始 while(remain>0) { cur=a[cur]; m++; if(m==n-1) { printf("%d, ",a[cur]); //t1=a[cur]; //t2=a[a[cur]]; a[cur]=a[a[cur]]; remain--; m=0; } } system("pause"); } (3)约瑟夫问题_链表 #include "stdio.h" #include "stdlib.h" struct people { int num; struct people *next; }; typedef struct people node; node *create(int m) { int i; node *h,*p1,*p2; h=p1=p2=(node *)malloc(sizeof(node)); h->num=1; for(i=1;i { p1=(node *)malloc(sizeof(node)); p2->next=p1; p1->num=i+1; p2=p1; } p1->next=h; return h; } node *findout(node *tp,int n) { int i; node *p; p=tp; for(i=1;i { p=p->next; } return p; } node *moveaway(node *tp) { node *c,*p1,*p2; c=tp; p1=c->next; p2=p1->next; c->next=p2; printf("%d, ",p1->num); free(p1); return p2; } void main() { node *p; int len,i,n; printf("请输入约瑟夫问题节点总数:"); len=41; //scanf("%d",&len); printf("请输入每次数的节点数字:"); n=3; //scanf("%d",&n); p=create(len); for(i=1;i<=len;i++) { p=moveaway(findout(p,n)); } system("pause"); } (4)约瑟夫问题_双向链表 #include "stdio.h" #include "stdlib.h" struct people { int num; struct people *next; struct people *prior; }; typedef struct people node; node *create(int m) { int i; node *h,*p1,*p2; h=p1=p2=(node *)malloc(sizeof(node)); h->num=1; for(i=1;i { p1=(node *)malloc(sizeof(node)); p2->next=p1; p1->prior=p2; p1->num=i+1; p2=p1; } p1->next=h; h->prior=p1; return h; } node *findout(node *tp,int n) { int i; node *p; p=tp; for(i=1;i { p=p->next; } return p; } node *moveaway(node *tp) { node *c,*p1,*p2; c=tp; p1=c->prior; p2=c->next; p1->next=p2; p2->prior=p1; printf("%d, ",c->num); free(c); return p2; } void main() { node *p; int len,i,n; printf("请输入约瑟夫问题节点总数:"); len=41;//scanf("%d",&len); printf("请输入每次数的节点数字:"); n=3;//scanf("%d",&n); p=create(len); for(i=1;i<=len;i++) { p=moveaway(findout(p,n)); } system("pause"); } 3.数字7 和5 (1)统计含有数字7,但不能被7整除的5位整数的个数#include #include void main() { int sum=0;//统计个数 int b;//起数 int a[6]; int have7; int j; int tempb; for(b=10000;b<100000;b++) { //分离数字到数组 tempb=b; for(j=0;j<5;j++) { a[5-j]=tempb-(tempb/10)*10; tempb=tempb/10; } //判断是否含7 have7=0; for(j=1;j<=5;j++) { if(a[j]==7) { have7++; } } if(have7>0 && b%7!=0) { //printf("%d\n",b); sum++; } } printf("sum=%d\n",sum); system("pause"); } (2)统计含有2个数字7,但不能被7整除的5位整数的个数#include #include void main() { int sum=0;//统计个数 int b;//起数 int a[6]; int have7; int j; int tempb; for(b=10000;b<100000;b++) { //分离数字到数组 tempb=b; for(j=0;j<5;j++) { a[5-j]=tempb-(tempb/10)*10; tempb=tempb/10; } //判断是否含7 have7=0; for(j=1;j<=5;j++) { if(a[j]==7) { have7++; } } if(have7==2 && b%7!=0) { printf("%d\n",b); sum++; } } printf("sum=%d\n",sum); system("pause"); } 4.百钱买百鸡:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡,问鸡翁、鸡母、鸡雏各几何? (1)#include #include void main() { int i,j,k; for(i=1;i<20;i++) { for(j=1;j<33;j++) { k=100-i-j; if(i*15+j*9+k==300) { printf("鸡翁%d,鸡母%d,鸡雏%d\n",i,j,k); } } } system("pause"); } (2)#include #include void main() { int i,j,k; for(i=1;i<20;i++) { for(j=1;j<33;j++) { k=(100-i*5-j*3)*3; if(i+j+k==100) { printf("鸡翁%d,鸡母%d,鸡雏%d\n",i,j,k); } } } system("pause"); } 5.逆序乘积式 (1)两位数逆序乘积式 #include void main() { int sum=0; int a,b,c,d; int i,j,ir,jr,m,n; int arr[5]; int flag; for(i=10;i<98;i++) { arr[1]=a=i/10; arr[2]=b=i-a*10; for(j=i+1;j<98;j++) { arr[3]=c=j/10; arr[4]=d=j-c*10; //检查有没有相同数字 flag=0; for(m=1;m<4;m++) { for(n=m+1;n<5;n++) { if(arr[m]==arr[n]) { flag=1; break; } } } //检查完 //右侧的逆序 ir=b*10+a; jr=d*10+c; if(flag==0&&i*j==ir*jr&&i { sum++; printf("%d:\ti=%d\t,j=%d\t,ir=%d\t,jr=%d\n",sum,i,j,ir,jr); } } } } (2)三位数逆序乘积式 #include void main() { int sum=0; int a,b,c,d,e,f; int i,j,ir,jr,m,n; int arr[7]; int flag; for(i=100;i<987;i++) { arr[1]=a=i/100; arr[2]=b=i/10-a*10; arr[3]=c=i-a*100-b*10; for(j=i+1;j<987;j++) { arr[4]=d=j/100; arr[5]=e=j/10-d*10; arr[6]=f=j-d*100-e*10; //检查有没有相同数字 flag=0; for(m=1;m<6;m++) { for(n=m+1;n<7;n++) { if(arr[m]==arr[n]) { flag=1; break; } } } //检查完 //右侧的逆序 ir=c*100+b*10+a; jr=f*100+e*10+d; if(flag==0&&i*j==ir*jr&&i { sum++; printf("%d:\ti=%d\t,j=%d\t,ir=%d\t,jr=%d\n",sum,i,j,ir,jr); } } } } 6.双和数组 (1)普通解法 #include void main() { int s; int a,b,c,d,e,f; int arr[7]; int flag,i,j; int sum=0; for (s=11;s<=100;s++) { printf("s=%d:\n",s); for(a=1;a<=s-2;a++) { for(b=a+1;b<=s-1;b++) { for(d=a+1;d<=s-2;d++) { for(e=d+1;e<=s-1;e++) { c=s-a-b; f=s-d-e; //检查是否有重复数字 arr[1]=a; arr[2]=b; arr[3]=c; arr[4]=d; arr[5]=e; arr[6]=f; if(a { flag=0; for(i=1;i<7;i++) { for(j=i+1;j<7;j++) { if(arr[i]==arr[j]) { flag=1; } } if(arr[i]<0) { //避免负数 flag=1; } } //没有重复的数字进入且符合倒数条件 if(flag==0&&(a*b*c*(e*f+f*d+d*e)==d*e*f*(b*c+c*a+a*b))) { sum++; printf("s=%d;a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",s,a,b,c,d,e,f); } } } } } } } printf("sum=%d",sum); } (2)优化后解法 #include void main() { int s; int a,b,c,d,e,f; int arr[7]; int flag,i,j; int sum=0; for (s=11;s<=100;s++) { printf("s=%d:\n",s); for(a=1;a<=s-2;a++) { for(b=a+1;b<=s-1;b++) { for(d=a+1;d<=s-2;d++) { for(e=d+1;e<=s-1;e++) { c=s-a-b; f=s-d-e; //检查是否有重复数字 arr[1]=a; arr[2]=b; arr[3]=c; arr[4]=d; arr[5]=e; arr[6]=f; flag=0; for(i=1;i<7;i++) { for(j=i+1;j<7;j++) { if(arr[i]==arr[j]) { flag=1; } } if(arr[i]<0) { //避免负数 flag=1; } } if(a>b||a>c||b>c) { flag=1; } if(d>e||d>f||e>f) { flag=1; } //没有重复的数字进入且符合倒数条件 if(flag==0&&(a*b*c*(e*f+f*d+d*e)==d*e*f*(b*c+c*a+a*b))) { sum++; printf("s=%d;a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",s,a,b,c,d,e,f); } } } } } } } 7.八皇后问题 (1)穷举法 #include #include #include #define N 8 //定义棋盘大小 void main(void) { int numoftimes = 0; int count = 0; int a[N + 1]; int flag; int i1, i2, i3, i4, i5, i6, i7, i8, x, y, p; printf("%d皇后问题的穷举法解决",N); for (i1 = 1; i1 <= N; i1++) { a[1] = i1; for (i2 = 1; i2 <= N; i2++) { a[2] = i2; for (i3 = 1; i3 <= N; i3++) { a[3] = i3; for (i4 = 1; i4 <= N; i4++) { a[4] = i4; for (i5 = 1; i5 <= N; i5++) { a[5] = i5; for (i6 = 1; i6 <= N; i6++) { a[6] = i6; for (i7 = 1; i7 <= N; i7++) { a[7] = i7; for (i8 = 1; i8 <= N; i8++) { a[8] = i8; //检测是否冲突 flag = 0; for (x = 1; x < N; x++) { for (y = x + 1; y <= N; y++) { if (a[x] == a[y] || abs(a[x] - a[y]) == y - x) { flag = 1; break; } numoftimes++; } if(flag==1) { continue; } } if (flag==0) { count++; printf("第%d种解法:", count); for (p = 1; p <= N; p++) { printf("%d", a[p]); } printf("\n"); } } } } } } } } } printf("共运行计算%d次\n", numoftimes); printf("共找到%d种方案\n", count); system("pause"); } (2)递归法 #include "stdio.h" #define N 8 //定义棋盘大小 static int count,a[N]; // count记录当前已找到解的个数 // a[N]记录皇后的位置,表示第i行的皇后放在棋盘的第a[i]列 int numoftimes = 0; void recursive(int t) { //尝试第t行的放置方案 int i; int j; int sign = 1; if (t == N + 1) { //t == N + 1 //表示放下最后一个皇后,找到解法 count++; /* 第1种显示方法 */ // t == N + 1 // 已经得到一个解决方案 printf("第%d种解法:", count); //Literal1.Text += string.Format("第{0}种解法:", count); for (i = 1; i <= N; i++) { printf("%d",a[i]); //Literal1.Text += string.Format("{0}", a[i]); } printf("\n"); //Literal1.Text += " /* 第2种显示方法 printf("第%d种解法:\n", count); for (i = 0; i < N; i ++) { for (j = 0; j < N; j ++) { if (j == a[i]) { printf("@ "); } else { printf("* "); } } printf("\n"); } printf("\n"); */ } else { //还没有放下所有的皇后 for (i = 1; i <= N; i++) { //依次尝试在第t行的第1列到第N列放置 a[t] = i; sign = 1; for (j = 1; j <= t - 1; j++) { //测试皇后在第t行第a[t]列时是否与前面已放置好的皇后相攻击。 //a[j] ==a[t] 时,两皇后在同一列上; //abs(t - j) == abs(a[j] - a[t]) 时,两皇后在同一斜线上。 //两种情况两皇后都可相互攻击,故不符合条件。设置sign=0 //if (Math.Abs(t - j) == Math.Abs(a[j] - a[t]) || (a[j] == a[t])) if (abs(t - j) == abs(a[j] - a[t]) || (a[j] == a[t])) { sign = 0; } numoftimes++; } //如果没有冲突,继续尝试 if (sign == 1) { recursive(t + 1); } else { //有冲突的方案丢弃! //也可以在此记录 } } } } void main(void) { recursive(1);//从第1行开始放置皇后 printf("运行%d次:", numoftimes); system("pause"); } (3)回溯法 #include #include #include #define N 8 void main() { int numoftimes = 0; int count = 0;//解法的个数(计数器) int a[N+1];//i,a[i]分别代表第i行和这行中皇后放置的列数 int flag;//标记0或1,0代表有冲突;1代表没有冲突 int i,j;//循环变量 int m; m=1;a[m] = 1;//从第1行开始第1行从第1列开始放置皇后 while (a[1] < N + 1 ) { numoftimes++; flag = 0; for (i = m - 1; i >= 1; i--) {//检查当前行放置位置,与之前的所有行有没有冲突 if (a[m] == a[i] || abs(a[m] - a[i]) == m - i) { flag = 1; break; } } if (flag==0 && m == N) { //检测是否找到合适的解 //如果所有的皇后位置没有冲突 flag==0 //并且m指向最后1行 m == N count++; printf("第%d种解法:", count); for (i = 1; i < N + 1; i++) { printf("%d", a[i]); } printf("\n"); } if (flag==0 && m < N) { //如果所有的皇后位置没有冲突 flag==0 //并且i尚未到达最后1行 m < N m++;//到下一行 a[m] = 1;//第1列 } else //if(flag==1||(flag==0&&m==N)) { //包括1 flag==1,有冲突 //包括2 没有冲突(flag==0 && m == N),已经输出的解法 //输出完后,也需要继续查找下一个解法 while (a[m] == N && m > 1) { //a[m] == N,已经测试完这一行的所有列,到达最后一列 // m > 1,不是第1行 m--;//退回上1行 } a[m]++;//右移1列 } } printf("共运行计算%d次\n", numoftimes); printf("共找到%d种方案\n\n", count); system("pause"); } 8.桥本分数式 (1)穷举法 #include #include //桥本分数式求解 void main() { int sum=0,runcount; int i1,i2,i3,i4,i5,i6,i7,i8,i9; int flag; int a[11]; int m,n,j; int left,right,ab; for(i1=1;i1<=9;i1++) { for(i2=1;i2<=9;i2++) { for(i3=1;i3<=9;i3++) { for(i4=1;i4<=9;i4++) { for(i5=1;i5<=9;i5++) { for(i6=1;i6<=9;i6++) { for(i7=1;i7<=9;i7++) { for(i8=1;i8<=9;i8++) { for(i9=1;i9<=9;i9++) { runcount++; a[1]=i1; a[2]=i2; a[3]=i3; a[4]=i4; a[5]=i5; a[6]=i6; a[7]=i7; a[8]=i8; a[9]=i9; //检查是否有重复数字 flag=0; for(m=1;m<9;m++) { for(n=m+1;n<10;n++) { if(a[m]==a[n]) { flag=1; } } } //检查重复完成
";