全部知识点
( 寻找假币 ) 现有 80枚硬币,其中有一枚是假币,其重量稍轻,所有真币的重量都相同,如果使 用不带砝码的天平称重,最少需要称几次,就可以找出假币?
( 取石子游戏 ) 现有 5 堆石子,石子数依次为 3,5,7,19,50,甲乙两人轮流从任一堆中任取 ( 每 次只能取自一堆,不能不取 ) ,取最后一颗石子的一方获胜。甲先取,问甲有没有获胜策略 ( 即无论 乙怎样取,甲只要不失误,都能获胜 ) ?如果有,甲第一步应该在哪一堆里取多少?请写出你的结果:
#include<stdio.h>
int main()
{
int i,u[4],a,b,x,y=10;
for(i=0;i<=3;i++)
scanf("%d",&u[i]);
a=(u[0]+u[1]+u[2]+u[3])/7;
b=u[0]/((u[1]-u[2])/u[3]);
x=(u[0]+a+2)-u[(u[3]+3)%4];
if(x>10)
y+=(b*100-u[3])/(u[u[0]%3]*5);
else
y+=20+(b*100-u[3])/(u[u[0]%3]*5);
printf("%d,%d\n",x,y);
return 0;
} /* 注:本例中,给定的输入数据可以避免分母为 0 或下标越界。 */输入: 9 3 9 4
输出: ________________
#include <stdio.h>
int main()
{
int i,j,m[]={2,3,5,7,13};
long t;
for(i=0;i<=4;i++)
{
t=1;
for(j=1;j<m[i];j++)
t*=2;
printf("%ld ",(t*2-1)*t);
}
printf("\n");
}输出: ________________
#include "stdio.h"
#define N 7
int fun(char s[],char a,int n)
{
int j;
j=n;
while(a<s[j]&&j>0) j--;
return j;
}
int main()
{
char s[N+1];
int k,p;
for(k=1;k<=N;k++)
s[k]='A'+2*k+1;
printf("%d\n",fun(s,'M',N));
}输出: ________________
#include <stdio.h>
void digit(long n,long m)
{
if(m>0)
printf("%2ld",n%10);
if(m>1)
digit(n/10,m/10);
printf("%2ld",n%10);
}
int main()
{
long x,x2;
printf("Input a number:\n");
scanf("%ld",&x);
x2=1;
while(x2<x)
x2*=10;
x2/=10;
digit(x,x2);
printf("\n");
}输入: 9734526
输出: ________________
( 全排列 ) 下面程序的功能是利用递归方法生成从 1 到 n(n<10) 的 n 个数的全部可能的排列 ( 不一定 按升序输出 ) 。例如,输入 3,则应该输出 ( 每行输出 5 个排列 ) :
123 132 213 231 321 312
程序:
#include<stdio.h>
int n,a[10]; /*a[1],a[2], …,a[n] 构成 n 个数的一个排列 */
long count=0; /* 变量 count 记录不同排列的个数,这里用于控制换行 */
void perm(int k)
{
int j,p,t;
if(______ ①______)
{
count++;
for(p=1;p<=n;p++)
printf("%1d",a[p]); /* "%1d" 中是数字 1,不是字母 l */
printf(" ");
if(______ ②______)
printf("\n");
return;
}
for(j=k;j<=n;j++)
{
t=a[k];
a[k]=a[j];
a[j]=t;
______③______;
t=a[k]; ______④______;
}
}
int main()
{
int i;
printf("Entry n:\n");
scanf("%d",&n);
for(i=1;i<=n;i++)
a[i]=i;
______⑤______;
}由键盘输入一个奇数 P(P<100,000,000) ,其个位数字不是 5,求一个整数 S,使 P×S=1111...1( 在给定的条件下,解 s 必存在) 。要求在屏幕上依次输出以下结果:
(1) S 的全部数字。除最后一行外,每行输出 50 位数字。
(2) 乘积的数字位数。
例 1:输入 P=13,由于 13*8547=111111,则应输出 (1) 8547 ,(2) 6
例 2:输入 P=147,则输出结果应为 (1) 755857898715041572184429327286470143613 (2) 42 ,即 等式的右端有 42个 1。
程序:
#include<stdio.h>
int main()
{
long p,a,b,c,t,n;
int bl;
while(1)
{
printf(" 输入 p, 最后一位为 1 或 3 或 7 或 9:\n");
scanf("%ld",&p);
if((p%2!=0)&&(p%5!=0)) /* 如果输入的数符合要求,结束循环 */
______⑥______;
}
a=0; n=0;
while(a<p);
{
a=a*10+1;n++;/*变量a存放部分右端项,n为右端项的位数*/
}
t=0;
do
{
b=a/p;
printf("%1ld",b);
t++;
if(___________⑦__________)
printf("\n");
c=_________⑧_________;a=________⑨______;n++;
}while(c>0);
printf("\nn=%ld\n".__________⑩_______);
}将 2006 个人分成若干不相交的子集,每个子集至少有 3 个人,并且:
(1)在每个子集中,没有人认识该子集的所有人。
(2)同一子集的任何 3 个人中,至少有 2 个人互不认识。
(3)对同一子集中任何 2 个不相识的人,在该子集中恰好只 有 1 个人认识这两个人。
则满足上述条件的子集最多能有 ___________个?
将边长为 n 的正三角形每边 n 等分,过每个分点分别做另外两边的平行线, 得到若干个正三角形,我们称为小三角形。正三角形的一条通路是一条连续的折线, 起点是最上面的一个小三角形,终点是最 下面一行位于中间的小三角形。在通路中, 只允许由一个小三角形走到另一个与其有公共边的且位于同 一行或下一行的小三 角形,并且每个小三角形不能经过两次或两次以上(图中是 n=5 时一条通路的 例 子)。设 n=10,则该正三角形的不同的通路的总数为_____________。

#include <stdio.h>
int main()
{
int i,u[4],v[4],x,y=10;
for(i=0;i<=3;i++)
scanf("%d", &u[i]);
v[0]=(u[0]+u[1]+u[2]+u[3])/7;
v[1]=u[0]/((u[1]-u[2])/u[3]);
v[2]=u[0]*u[1]/u[2]*u[3];
v[3]=v[0]*v[1];
x=(v[0]+v[1]+2)-u[(v[3]+3)%4];
if(x>10) 由 OIFans.c 收集
y+= (v[2]*100-v[3])/(u[u[0]%3]*5);
else
y+=20+(v[2]*100-v[3])/(u[v[0]%3]*5);
printf("%d,%d\n", x,y);
return 0;
} /* 注:本例中,给定的输入数据可以避免分母为 0 或下标越界。 */输入:9 3 9 4
输出:_______________
#include <stdio.h>
int main()
{
int i,j,m[]={2,3,5,7,13};
long t;
for (i=0;i<=4;i++)
{
t=1;
for(j=1;j<m[i];j++) t*=2;
printf("%ld ",(t*2-1)*t);
}
printf("\n");
}输出:____________________
#include "stdio.h"
#define N 7
int fun1(char s[],char a,int n)
{
int j;
j=n;
while(a<s[j] && j>0) j--;
return j;
}
int fun2(char s[],char a,int n)
{
int j;
j=1;
while(a>s[j] && j<=n) j++;
return j;
}
void main()
{
char s[N+1];
int k,p;
for(k=1;k<=N;k++)
s[k]='A'+2*k+1;
p=fun1(s,'M',N);
printf( “%d\n”,p+fun2(s,'M',N));
}输出:_____________
#include <stdio.h>
void digit(long n,long m)
{
if(m>0)
printf("%2ld",n%10);
if(m>1)
digit(n/10,m/10);
printf("%2ld",n%10);
}
int main()
{
long x,x2;
printf("Input a number:\n"); scanf("%ld",&x);
x2=1;
while(x2<x) x2*=10;
x2/=10;
digit(x,x2);
printf("\n");
}输入:9734526
输出:______________________________
(选排列)下面程序的功能是利用递归方法生成从 1 到 n(n<10)的 n 个数中取 k(1<=k<=n)个数的 全部可能的排列(不一定按升序输出)。
例如,当 n=3,k=2 时, 应该输出(每行输出 5 个排列):
12 13 21 23 32
31
程序:
#include <stdio.h>
int n,k,a[10];
long count=0;
void perm2(int j)
{
int i,p,t;
if( ① )
{
for(i=k;i<=n;i++)
{
count++;
t=a[k]; a[k]=a[i]; a[i]=t;
for( ② )
printf("%1d",a[p]); /* "%1d" 中是数字 1,不是字母 l */
printf(" ");
t=a[k];a[k]=a[i];a[i]=t;
if(count%5==0) printf("\n");
}
return;
}
for(i=j;i<=n;i++)
{
t=a[j];a[j]=a[i];a[i]=t;
③ ;
t=a[j]; ④ ;
}
}
int main()
{
int i;
printf("\nEntryn,k (k<=n):\n");
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++) a[i]=i;
⑤ ;
}(TSP 问题的交叉算子) TSP 问题 (Traveling Salesman Problem) 描述如下: 给定 n 个城市, 构成一个完全图,任何两城市之间都有一个代价(例如路程、旅费等) ,现要构造遍历所有 城市的环路,每个城市恰好经过一次,求使总代价达到最小的一条环路。 遗传算法是求解该问题的一个很有效的近似算法。 在该算法中, 一个个体为一条环路, 其编 码方法之一是 1 到 n 这 n 个数字的一个排列, 每个数字为一个城市的编号。 例如当 n=5 时, “ 3 4 2 1 5 表示该方案实施的路线为 ” 3->4->2->1->5->3 。遗传算法的核心是通过两个个体的 交叉操作,产生两个新的个体。下面的程序给出了最简单的一种交叉算法。
具体过程如下:
(1)选定中间一段作为互换段,该段的起止下标为 t1,t2,随机生成 t1,t2 后,互换两段。
(2)互换后,在每个新的排列中可能有重复数字,因而不能作为新个体的编码,一般再做两 步处理:
(2.1) 将两个互换段中,共同的数字标记为 0,表示已处理完。
(2.2) 将两个互换段中其余数字标记为 1,按顺序将互换段外重复的数字进行替换。
例如: n=12,两个个体分别是:
a1: 1 3 5 4 * 2 6 7 9 * 10 12 8 11
a2: 3 2 1 12 * 6 7 10 11 * 8 5 4 9 t1=5,t2=8。
上述每一行中,两个星号间的部分为互换段。假定数组的下标从 1 开始,互换 后有:
a1: 1 3 5 4 * 6 7 10 11 * 10 12 8 11
a2: 3 2 1 12 * 2 6 7 9 * 8 5 4 9
然后,将数字 6,7 对应的项标记为 0,星号内数字 2,9,10,11 对应的项标记为 1,并且按顺序 对应关系为 : 10<->2 ,11<->9。于是,将 a1[9]=10 替换为 a1[9]=2 ,将 a2[2]=2 替换为 a2[2]=10 , 类似再做第 2 组替换。这样处理后,就得到了两个新个体:
a1: 1 3 5 4 6 7 10 11 2 12 8 9
a2: 3 10 1 12 2 6 7 9 8 5 4 11
(3)输出两个新个体的编码。
程序:
#include <stdio.h>
#include <stdlib.h>
#define N 20
int a1[N],a2[N],kz1[N],kz2[N],n;
int rand1(int k)
{
int t=0;
while(t<2|| t>k)
t=(int)((double)rand()/RAND_MAX*k);
return t;
}
void read1(int a[],int m)
{ 读入数组元素 a[1]至 a[m], a[0]=0 ,略. }
void wrt1(int a[],int m)
{ 输出数组元素 a[1]至 a[m],略. }
void cross(int a1[], int a2[],int t1, int t2, int n)
{
int i,j,k,t,kj;
for(i=t1; i<=t2; i++)
{
t=a1[i]; ①;
}
for(i=1;i<=n;i++)
if(i<t1 || i>t2)
kz1[i]=kz2[i]=-1;
else
②;
for(i=t1;i<=t2;i++)
for(j=t1;j<=t2;j++)
if(a1[i]==a2[j])
{
③ ; break;
}
for(i=t1;i<=t2;i++)
if(kz1[i]==1)
{
for(j=t1;j<=t2;j++)
if(kz2[j]==1)
{
kj=j; break;
}
for(j=1;j<=n;j++)
if( ④ )
{
a1[j]=a2[kj];break;
}
for(j=1;j<=n;j++)
if( ⑤ )
{
a2[j]=a1[i]; break;
}
kz1[i]=kz2[kj]=0;
}
}
int main()
{
int k,t1,t2;
printf("input (n>5):\n"); scanf("%d",&n);
printf("input array 1 (%d'numbers):\n",n); read1(a1,n);
printf("input array 2 (%d'numbers):\n",n); read1(a2,n);
t1=rand1(n-1);
do
{
t2=rand1(n-1);
}while(t1==t2);
if(t1>t2)
{
k=t1; t1=t2; t2=k;
}
⑥
wrt1(a1,n); wrt1(a2,n);
}(子集划分)将 n 个数{1,2,…,n}划分成 r 个子集。每个数都恰好属于一个子集,任何两个 不同的子集没有共同的数,也没有空集。将不同划分方法的总数记为 S(n,r)。例如,S(4,2)=7,这 7 种不同的划分方法依次为{(1),(234)}, {(2),(134)}, {(3),(124)}, {(4),(123)}, {(12),(34)}, {(13),(24)}, {(14),(23)}。当 n=6,r=3 时,S(6,3)= _____________。
(提示:先固定一个数,对于其余的 5 个数考虑 S(5,3)与 S(5,2),再分这两种情况对原固定的数 进行分析)。
(最短路线)某城市 的街道是一个很规整的矩形网格(见下图),有 7 条南北向的纵街,5 条东 西向的横街。现要从西南角的 A 走到东北角的 B,最短的走法共有多少种?_________________.

#include <iostream.h>
void main()
{
int i,p[5],a,b,c,x,y=20;
for(i=0;i<=4;i++) cin>>p[i];
a=(p[0]+p[1])+(p[2]+p[3]+p[4])/7;
b=p[0]+p[1]/((p[2]+p[3])/p[4]);
c=p[0]*p[1]/p[2];
x=a+b-p[(p[3]+3)%4];
if(x>10)
y+= (b*100-a)/(p[p[4]%3]*5);
else
y+=20+(b*100-c)/(p[p[4]%3]*5);
cout<<x<<","<<y<<endl;
}
// 注:本例中,给定的输入数据可以避免分母为 0 或数组元素下标越界。输入:6 6 5 5 3 输出:_______________
#include <iostream.h>
void fun(int *a,int *b)
{
int *k;
k=a; a=b; b=k;
}
void main( )
{
int a=3, b=6, *x=&a, *y=&b;
fun(x,y);
cout<<a<<","<<b<<endl;
}输出:____________________