数学问题.docx

上传人:b****5 文档编号:30671446 上传时间:2023-08-19 格式:DOCX 页数:30 大小:27.53KB
下载 相关 举报
数学问题.docx_第1页
第1页 / 共30页
数学问题.docx_第2页
第2页 / 共30页
数学问题.docx_第3页
第3页 / 共30页
数学问题.docx_第4页
第4页 / 共30页
数学问题.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

数学问题.docx

《数学问题.docx》由会员分享,可在线阅读,更多相关《数学问题.docx(30页珍藏版)》请在冰豆网上搜索。

数学问题.docx

数学问题

9.1多项式展开系数

源程序名equal.?

?

?

(pas,c,cpp)

可执行文件名equal.exe

输入文件名equal.in

输出文件名equal.out

【问题描述】

二项式展开系数大家已经十分熟悉了:

n!

C=————

(i!

*(n-i)!

现在我们将问题推广到任意t个实数的和的n次方(x1+x2+…+xt)n的展开式。

我们想知道多项式(x1+x2+…+xt)n中的任意一项x1n1x2n2…xini的系数。

例如,将一个三项式(x1+x2+x3)3展开后,可以得到:

(x1+x2+x3)3=x13+x23+x33+3x12x2+3x12x3+3x1x22+3x1x32+3x22x3+3x2x32+6x1x2x3其中,x21x2的系数为3

【输入】

第一行,两个整数n和t,中间用空格分隔。

分别表示多项式幂和项数。

第二行,t个整数n1,n2,…,nt,中间用空格分隔。

分别表示x1,x2,…,xn的幂。

(n1+n2+…+nt=n,1≤n,t≤12)

【输出】

仅一行,一个整数(保证在长整型范围内)。

表示多项式(x1+x2+…+xt)n中的项x1n1x2n2…xtnt的系数。

【样例】

equal.inequal.out

333

210

【知识准备】

组合数运算;二项式展开;代数式的恒等变形。

【算法分析】

我们可以从二项式定理推广到多项式定理,得出系数的通项公式为

n!

/(n1!

n2!

…nt-1!

nt!

【参考程序】

programgdjk;

vari,n,t,sum:

longint;

f:

array[0..12]oflongint;

c:

array[1..12]oflongint;

begin

assign(input,'equal.in');

reset(input);

assign(output,'equal.out');

rewrite(output);

f[0]:

=1;

fori:

=1to12do//计算1~12的阶乘

f[i]:

=f[i-1]*i;

readln(n,t);

fori:

=1totdo

read(c[i]);

sum:

=f[n];

fori:

=1totdo

sum:

=sumdivf[c[i]];//求系数

writeln(sum);

close(input);

close(output);

end.

9.2两数之和

源程序名pair.?

?

?

(pas,c,cpp)

可执行文件名pair.exe

输入文件名pair.in

输出文件名pair.out

【问题描述】

我们知道从n个非负整数中任取两个相加共有n*(n-1)/2个和,现在已知这n*(n-1)/2个和值,要求n个非负整数。

【输入】

输入文件仅有一行,包含n*(n-1)/2+1个空格隔开的非负整数,其中第一个数表示n(2

【输出】

输出文件仅一行,按从小到大的次序依次输出一组满足要求的n个非负整数,相邻两个整数之间用一个空格隔开;若问题无解则输出“Impossible”。

【样例】

pair.inpair.out

3126911601663383777886

【算法分析】

此题一眼看到会觉得没有任何思路,唯一的想法就是搜索,结果证明这一想法是正确的。

我们应该先求出最小数,因为最小数求出来以后,第二小的数,第三小的数,……,都求出来的,但如何求最小数呢?

我们先将序列从小到大排序,枚举1~a[1]中的所有数设为最小数f[1],再一个一个求出其他数如何求其他数呢,我们这样想,数列a中第二小的数一定是a[2]=f[1]+f[2],于是f[2]=a[2]-f[1],同理f[3]=a[3]-f[1],将f[1]~f[3]产生的和从数组a中去除,在重复以上过程

【参考程序】

programfjl;

typearr=array[1..45]oflongint;

varn,i,j,s,k,l,t:

longint;

a,f,b:

arr;

q,p:

boolean;

proceduresort(vara:

arr);

vari,j,t:

longint;

begin

fori:

=1tos-1do

forj:

=1tos-ido

ifa[j+1]

begin

t:

=a[j+1];

a[j+1]:

=a[j];

a[j]:

=t;

end;

end;{sort}

functionfind(x:

longint):

longint;//在数组b中找数x

vari:

byte;

begin

fori:

=1tosdo

ifb[i]=xthen

exit(i);

exit(0);

end;{find}

begin{main}

assign(input,'pair.in');

reset(input);

assign(output,'pair.out');

rewrite(output);

read(n);

s:

=n*(n-1)div2;//个数

fori:

=1tosdo

read(a[i]);

sort(a);//将a排序

q:

=false;

k:

=(a[1])div2;//最小数的上限

fori:

=1tokdo//枚举最小数

begin

fillchar(f,sizeof(f),0);

b:

=a;

f[1]:

=i;

f[2]:

=b[1]-f[1];

b[1]:

=0;//删去b[1]

f[3]:

=b[2]-f[1];

b[2]:

=0;//删去b[2]

iffind(f[2]+f[3])>0thenb[find(f[2]+f[3])]:

=0

elsecontinue;

t:

=3;

repeat

sort(b);

forj:

=3tosdo

if(b[j]<>0)then

begin

inc(t);

f[t]:

=b[j]-f[1];

b[j]:

=0;//删去b[j]

p:

=false;

forl:

=2tot-1do

iffind(f[l]+f[t])>0thenb[find(f[l]+f[t])]:

=0

elsebegin

p:

=true;//不成立

break;

end;

end;

ifpthenbreak;//当前数不成立

until(f[n]>0)or(p=true);

if(f[n]>0)and(notp)then

begin

q:

=true;

forl:

=1ton-1do//输出解

write(f[l],'');

writeln(f[n]);

close(input);

close(output);

halt;

end;

end;

ifnotqthenwriteln('Impossible');//无解

close(input);

close(output);

end.

9.3盒子与球

源程序名box.?

?

?

(pas,c,cpp)

可执行文件名box.exe

输入文件名box.in

输出文件名box.out

【问题描述】

现有r个互不相同的盒子和n个互不相同的球,要将这n个球放入r个盒子中,且不允许有空盒子。

问有多少种方法?

例如:

有2个不同的盒子(分别编为1号和2号)和3个不同的球(分别编为1、2、3号),则有6种不同的方法:

1号盒子1号球1、2号球1、3号球2号球2、3号球3号球

2号盒子2、3号球3号球2号球1、3号球1号球1、2号球

【输入】

两个整数,n和r,中间用空格分隔。

(0≤n,r≤10)

【输出】

仅一行,一个整数(保证在长整型范围内)。

表示n个球放入r个盒子的方法。

【样例】

box.in

32

box.out

6

【知识准备】

第二类Stirling数。

【算法分析】

先考虑三种情况:

(1)若盒子数r大于球数n,根据题意不允许有空盒的要求,放置的方法数为零;

(2)若r=1,则只有一种放法;

(3)若r=n,相当于将n个不同的球进行排列,故有n!

种。

下面考虑1

n个不同的球放入r个不同的盒子中,可以先把r个盒子视为相同的,即先求出n个不同的球放入r个相同的盒子中,且不允许有空盒子的不同方案数,设为S(n,r);再将r个盒子进行全排列,共有r!

记号f(n,r)为n个不同的球放入r个不同盒子中,且不允许有空盒子的不同放法,根据乘法原理,有f(n,r)=S(n,r)·r!

如何求S(n,r)?

请看如下定义:

定义n个有区别的球放入r个相同的盒子中,要求无一空盒,其不同的方案数s(n,r)称为第二类Stirling数。

S(n,r)=r·S(n-1,r)+S(n-1,r-1)(n>1,r≥1)

证明:

设n个不同的球为b1,b2,…,bn,从中取一个球设为b1。

把这n个球放入r个盒子无一空盒的方案全体可分为两类:

(1)b1独占一盒,其余n-1个球放入r-1个盒子无一空盒的方案数为S(n-1,r-1)

(2)b1不独占一盒,这相当于先将b2,b3,…,bn。

这n-1个球放入r个盒子,不允许有空盒的方案数共有S(n-1,r),然后将b1放入其中一盒,这一盒子有r种可挑选,故b1不独占一盒的方案数为r·S(n-1,r)。

根据加法原理,则有:

S(n,r)=r·S(n-1,r)+S(n-1,r-1)(n>1,r≥1)

对于n=r,或r=1,显然有S(n,n)=1,S(n,1)=1。

综上所述,本题的算法可用第二类Stirling数的递推关系先求出S(n,r),再乘上r!

,即得所求方案数。

【参考程序】

programfgduif;

varn,r,j,i:

longint;

s:

array[0..20,0..20]oflongint;

begin

assign(input,'box.in');

reset(input);

assign(output,'box.out');

rewrite(output);

fillchar(s,sizeof(s),0);

readln(n,r);

fori:

=1tondo

forj:

=1tordo

ifi=jthens[i,j]:

=1

elseifj=1thens[i,j]:

=1

elses[i,j]:

=j*s[i-1,j]+s[i-1,j-1];//求第二类Stirling数

fori:

=1tordo

s[n,r]:

=s[n,r]*i;

writeln(s[n,r]);

close(input);

close(output);

end.

9.4

取数游戏

源程序名cycle.?

?

?

(pas,c,cpp)

可执行文件名cycle.exe

输入文件名cycle.in

输出文件名cycle.out

【问题描述】

有一个取数的游戏。

初始时,给出一个环,环上的每条边上都有一个非负整数。

这些整数中至少有一个0。

然后,将一枚硬币放在环上的一个节点上。

两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流取数,取数的规则如下:

(1)选择硬币左边或者右边的一条边,并且边上的数非0;

(2)将这条边上的数减至任意一个非负整数(至少要有所减小);

(3)将硬币移至边的另一端。

如果轮到一个玩家走,这时硬币左右两边的边上的数值都是0,那么这个玩家就输了。

如下图,描述的是Alice和Bob两人的对弈过程,其中黑色节点表示硬币所在节点。

结果图(d)中,轮到Bob走时,硬币两边的边上都是0,所以Alcie获胜。

2000

○----------○○-----------○○----------○○---------○

||||||||

0||50||50||10||0

||||||||

○--------------○○----------○○----------○○---------○

3333

(a)Alice(b)Bob(c)Alice(d)Bob

现在,你的任务就是根据给出的环、边上的数值以及起点(硬币所在位置),判断先走方是否有必胜的策略。

【输入】

第一行一个整数N(N≤20),表示环上的节点数。

第二行N个数,数值不超过30,依次表示N条边上的数值。

硬币的起始位置在第一条边与最后一条边之间的节点上。

【输出】

仅一行。

若存在必胜策略,则输出“YES”,否则输出“NO”。

【样例】

cycle.incycle.out

4YES

2530

cycle.incycle.out

3NO

000

【问题分析】

考虑一个简化的问题。

如果硬币的一边的数值为0,那么惟一可能取胜的走法就是向另一边移动,并且把边上的数减到0。

因为如果不把边上的数减到0,那么下一步对方会将硬币移动到原来的位置,并且将边上的数减到0,这样硬币两边的数值就都为0了。

所以,对于一边有0的情况,双方惟一的走法就是不停的向另一边移动,并取完边上的数值。

因此,判断是否有必胜策略,就是看另一个方向上连续的非零边是否为奇数条。

那么两边都非零的情况呢?

如果有一个方向上连续的非零边为奇数条,那么显然是有必胜策略的,因为只需往这个方向走并取完边上的数即可。

如果两个方向上连续的非零边都是偶数条,则没有必胜策略。

因为不管往哪个方向走,必然不能取完边上的数,否则必败。

如果不取完,则下一步对方可以将硬币移动回原来的位置并取完边上的数,这样就变成了一边为0、另一边有偶数条连续的非零边的情况,还是必败。

所以,对于一般的情况,只需判断硬币的两边是否至少有一边存在奇数条连续的非零边。

如果存在,则有必胜策略;否则无必胜策略。

算法的时间复杂度为O(N)。

【参考程序】

programcgfdj;

vari,n,left,right:

longint;//left表示左边有几个连续非零数,right表示右边有几个连续非零数

a:

array[1..20]oflongint;

begin

assign(input,'cycle.in');

reset(input);

assign(input,'cycle.out');

rewrite(output);

readln(n);

fori:

=1tondo

read(a[i]);

left:

=0;

right:

=0;

fori:

=1tondo

ifa[i]<>0theninc(right)//统计右边

elsebreak;

fori:

=ndownto1do

ifa[i]<>0theninc(left)//统计左边

elsebreak;

ifodd(left)orodd(right)thenwriteln('YES')//有必胜策略

elseif(notodd(left))and(notodd(right))thenwriteln('NO');//无必胜策略

close(input);

close(output);

end.

9.5磁盘碎片整理

源程序名defrag.?

?

?

(pas,c,cpp)

可执行文件名defrag.exe

输入文件名defrag.in

输出文件名defrag.out

【问题描述】

出于最高安全性考虑,司令部采用了特殊的安全操作系统,该系统采用一个特殊的文件系统。

在这个文件系统中所有磁盘空间都被分成了相同尺寸的N块,用整数1到N标识。

每个文件占用磁盘上任意区域的一块或多块存储区,未被文件占用的存储块被认为是可是用的。

如果文件存储在磁盘上自然连续的存储块中,则能被以最快的速度读出。

因为磁盘是匀速转动的,所以存取上面不同的存储块需要的时间也不同。

读取磁盘开头处的存储块比读取磁盘尾处的存储块快。

根据以上现象,我们事先将文件按其存取频率的大小用整数1到K标识。

按文件在磁盘上的最佳存储方法,1号文件将占用1,2,…,S1的存储块,2号文件将占用S1+1,S1+2,…,S1+S2的存储块,以此类推(Si是被第i个文件占用的存储块的个数)。

为了将文件以最佳形式存储在磁盘上,需要执行存储块移动操作。

一个存储块移动操作包括从磁盘上读取一个被占用的存储块至内存并将它写入其他空的存储块,然后宣称前一个存储块被释放,后一个存储块被占用。

本程序的目的是通过执行最少次数的存储块移动操作,将文件安最佳方式存储到磁盘上,注意同一个文件的存储块在移动之后其相对次序不可改变。

【输入】

每个磁盘说明的第一行包含两个用空格隔开的整数N和K(1≤K≤N≤100000),接下来的K行每行说明一个文件,对第i个文件的说明是这样的:

首先以整数Si开头,表示第i个文件的存储块数量,1<=Si<=N-K,然后跟Si个整数,每个整数之间用空格隔开,表示该文件按自然顺序在磁盘上占用的存储块的标识。

所有这些数都介于1和N之间,包括1和N。

一个磁盘说明中所有存储块的标识都是不同的,并且该盘至少有一个空的存储块。

【输出】

对于每一个磁盘说明,只需输出一行句子“WeneedMmoveoperations”,M表示将文件按最佳方式存储到磁盘上所需进行的最少存储块移动操作次数。

如果文件已按最佳方式存储,仅需输出“Nooptimizationneeded.”。

【样例】

defrag.indefrag.out

203Weneed9moveoperations

4231112

17

318510

【问题分析】

本题可以看作是一个置换的调整问题。

按文件块的目标位置对文件块编号后,调整文件块位置的问题就转化为调整置换的问题了。

不过,本题还有一点特殊之处,就是存在一些数,它们不要求归位,这些数可作为交换空间。

找出所有的循环节,分情况讨论。

如果是一条链,则只需移动链的长度次,若是一个环则需要移动环的长度+1次

【参考程序】

programfgjk;

varn,k,s,i,j,m,t:

longint;

a:

array[1..100000]oflongint;

v:

array[1..100000]ofboolean;

begin

assign(input,'defrag.in');

reset(input);

assign(output,'defrag.out');

rewrite(output);

fillchar(a,sizeof(a),0);

fillchar(v,sizeof(v),false);

readln(n,k);

m:

=0;

fori:

=1tokdo

begin

read(s);

forj:

=1tosdo

begin

read(t);

inc(m);

a[m]:

=t;

ifm=tthenv[t]:

=true;//已经处于原来位置

end;

end;

s:

=0;

fori:

=1tomdo

ifnotv[a[i]]then//判断是否需要移动

begin

k:

=a[i];

j:

=a[i];//记住初始位置

t:

=0;

repeat//寻找链或环

v[k]:

=true;

inc(t);

k:

=a[k];

until(k=0)or(v[k]);//得到一条链或一个环

ifk=0theninc(s,t)//得到的是链

elseifk=jtheninc(s,t+1)//得到的为环

elseinc(s,t);//得到的是链

end;

ifs>0thenwriteln('Weneed',s,'moveoperations.')

elsewriteln('Nooptimizationneeded.');

close(input);

close(output);

end.

9.6欧几里德的游戏

源程序名game.?

?

?

(pas,c,cpp)

可执行文件名game.exe

输入文件名game.in

输出文件名game.out

【问题描述】

欧几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的。

给定两个正整数M和N,从Stan开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数不能小于0。

然后是Ollie,对刚才得到的数,和M,N中较小的那个数,再进行同样的操作……直到一个人得到了0,他就取得了胜利。

下面是他们用(25,7)两个数游戏的过程:

Start:

257

Stan:

117

Ollie:

47

Stan:

43

Ollie:

13

Stan:

10

Stan赢得了游戏的胜利。

现在,假设他们完美地操作,谁会取得胜利呢?

【输入】

第一行为测试数据的组数C。

下面有C行,每行为一组数据,包含两个正整数M,N。

(M,N不超过长整型。

【输出】

对每组输入数据输出一行,如果Stan胜利,则输出“Stanwins”;否则输出“Olliewins”

【样例】

game.ingame.out

2Stanwins

257Olliewins

2415

【问题分析】

这是一道博弈题。

解题的关键在于把握胜负状态的关系。

任意的状态只有两种可能:

一种可能是胜状态——即有必胜策略,另一种可能是负状态——即没有必胜策略。

对于任意的胜状态,无论如何走,都不可能走到另一个胜状态;而任意的负状态,至少存在一种走法可以走到胜状态。

(0,0)是初始的胜状态。

考察任意的状态(a,b),不妨假设a≥b。

如果a/b<2,则只有一种走法,即将(a,b)变为(a-b,b)。

那么,(a,b)是何种状态就取决于(a-b,b)是何种状态:

根据前面胜负状态的定义可知,(a-b,b)为胜状态时,(a,b)为负状态;(a-b,b)为负状态时,(a,b)为胜状态。

如果a/b≥2,则至少存在两种走法:

将(a,b)变为(c,b)或(c+b,b),这里c=amodb。

如果这两个状态中至少有一个是负状态,则根据定义(a,b)是胜状态。

如果两个状态都是胜状态,由于(c+b,b)可以变为(c,b),这就与“胜状态只能走到负状态”产生了矛盾,所以两个状态都是胜状态的情况是不存在的。

因此,a/b≥2时,(a,b)必为胜状态。

总结一下前面的

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 少儿英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1