故事中的主角有很多半途而废的机会,但他们并没有
本周比较特殊,由于我这周参加了美赛所以给大家的博客耽误了一点,所以今天咱们先在这分享以下我第一次美赛的感受和想法。 (干货来了)
- 学会找资料真的很重要,没有数据的数学建模就是语文建模,空口无凭。找资料的方法有很多种,从娱乐新闻里挖掘,从知网的论文中挖掘,从官方网站寻找(比如国家统计局、税务局、FAO的官网等等等等,只要能找到数据)如果自己学会了python也可以自己爬,然后如果你发现你在国内找不到你需要的数据,尝试*(途径自己去寻找)。比如我这次做美赛,就是有关沙雕的,求什么样的简单三维几何体作为沙堡的地基更耐用以及沙水比为多少时最合适。我们查到的大多数资料都是外网上的,国内研究沙子的好像不多,没有找到太多相关的数据和论文(可能是我太菜了)
- 英语真的也很重要,这样对论文的写作和英语论文的阅读都有好处。哪怕论文大部分用谷歌翻译完了,但是自己一定要看一遍,因为机翻实在是不太靠谱。
- 美赛也很重要,所以一定要很重视,毕竟它在我们学校也算A类,拿奖概率相对于国赛也要高一点
- 。。。其他的我好像也没啥可分享了(就这样吧,还有问题就下方留言解答吧)
好了好了,我们接着上次的来,这次题目不多
Matlab官方帮助文档
1-26
这个题涉及到矩阵的操作,还有一些线性(高等)代数中的名词。常用函数记一下就问题不大
clc;clear;
a=[1:100];
a=reshape(a,10,10)';
disp('a的行列式为:');
det(a)
disp('a矩阵左右翻转后如下:');
b=fliplr(a)
disp('a的逆矩阵为:');
c=inv(a) %或者A^(-1)
disp('a的特征值和特征向量为:');
[d,e]=eig(a);
d
e=diag(e)
disp('a逆时针旋转270后如下:');
f=rot90(a,3)
disp('a删除第6行和第4行后为:');
i=a; i(6,:)=[]; i(:,4)=[]
disp('a矩阵第7行交换后为:')
j=a; j(7,:)=7
1-27
1-27本身其实很简单,一个奇偶数判断即可(代码如下)。但是——我们来学点小的新知识:位运算
clc;clear;
n=input('请输入一个自然数:');
while n~=1
if mod(n,2)==0
n=n/2;
else
n=3*n+1;
end
end
n
我们知道,计算机计算是2进制计算,那么位运算就是直接对整数在内存中的二进制位进行操作,位运算虽然运算优先级较低,但是却算的很快。用位运算判断奇偶比取余判断奇偶大约快4倍(摘自一位博主的结论),在数据量较大时差距很明显,如要判断104次甚至更大时。那么,如何用位运算进行操作呢?
奇数如果用二进制表示,那么最低位一定是1。在之前的二进制转换时我们知道,二进制转化为十进制数时,是按照权重计算的,如:(括号内数代表为几进制)
X(10)=nnnn−1......n1n(2)=nn∗2n+nn−1∗2n−1+......+n1∗21+n∗20
⟹该式前n项相加一定是偶数(2的次幂相加)[注:nn,nn−1,......n1,n为0或1]
⟹ X的奇偶性取决于最后一项,也就是n∗20,如果最后一位n=1,那么一定是奇数;如果为0,则为偶数。(这个地方很关键)
有了上面的基础,我们再来理解一下按位与是什么。简单来讲就是把每一位数字进行与运算。1&1=1,1&0=0,0&0=0,0&0=0;
举个栗子:
eg.1 1011 & 1 (不足就补前置0,一位一位的进行与运算) || eg.2 100 & 1
1011(2)===>11(10) || 100(2)===>8(10)
& 0001(2)===> 1(10) || & 001(2)===>1(10)
——————————————————— || ————————————————————
= 0001(2)===> 1(10) || = 000(2)===>0(10)
可以看到,11&1结果为1,所以11为奇数,8&1结果为0,8为偶数。
所以把第一次mod判断的代码做一下修改,mod(n,2)==0
改为bitand(a,1)==0
即可(C语言是n&1==0
),bitand是matlab按位与函数。
还介绍一个小技巧:利用位运算巧判一个数是否是2的幂次方
看上面的eg.2,我们观察规律会发现:将2的幂次方写成二进制形式后,二进制中只有一个1,并且1后面跟了n个0。 我们如果将这个二进制数减去1后会发现,仅有的那个1会变为0,而原来的那n个0会变为1;再将将原来的数与减去1后的数字进行按位与运算后会发现为结果零。(是不是很妙!!!)
(啥?还没想明白?)那看个栗子好了:
1000(2)===>16(10)=================>||=============> 1000(2)
- 0001(2)===> 1(10) ||=============> & 0111(2)
—————————————————— || ——————————
= 0111(2)===========================>|| = 0000(2)===>0(10)
看明白了吧!如果不用位运算,那你只能暴力破解,比这就麻烦多了。。。
位运算还有其他很妙的用法,具体的就可以自己感兴趣去了解一下了(比如左移、异或、取反…)
1-28
这个题目是一个简单的排序题。。。把LA和LB合并一下就行,然后再用sort函数排一下序。(本来初衷是想让你们用冒泡做的,结果忘记加备注让你们不要用sort了。。。。。。)(突然想起来有一次讲题的时候本来要讲冒泡结果忘记了…这次就补起来吧)
先给一下sort的方法。
clc;clear;
n=input('请输入数组LA的元素个数:');
LA=input('请输入非递减数组LA:');
m=input('请输入数组LB的元素个数:');
LB=input('请输入非递减数组LB:');
disp('合并后的数组LC为:');
LC=sort([LA LB])
再来讲排序。排序的算法有很多,这里暂时就只讲冒泡。以后我可能会出一个排序算法的总结吧(再次成功的挖了一个大坑) 不过还是给有兴趣的同学介绍一下(不感兴趣的就直接跳到冒泡排序,这个还是要看看的),排序算法大致可以分为两种:比较排序和非比较排序。我们通常说的排序通常是只数据在内存中进行排序。
比较排序:时间复杂度O(nlogn)~O(n2)。主要有冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序等
非比较排序:时间复杂度可达O(n)。主要有:基数排序、计数排序、桶排序等。
冒泡排序
冒泡排序基本上会是所有学编程的人学会的第一个排序算法。核心在于依次比较相邻两个元素,如果顺序不符合要求就两两交换,符合就进行下一组,直到没有元素再交换,排序完成。
具体如下:
1.比较相邻的元素,如果不符合你的排序要求(在从小到大中,假如前一个比后一个大,那就不符合我们的排序要求。下面的操作为方便叙述,举的是从小到大排序的例子),于是把它们两两交换。
2.对每一对相邻元素重复1操作,从开始第一对到结尾的最后一对。第二步做完后,最后一个就是数组中最大的元素。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.重复上面的步骤,直到没有任何一对元素需要比较。
有一个博主的图片很棒,我就拿来借用了一下,对其他排序感兴趣的也可以戳他博客链接—>click me,里面有很多这样的动图,可以增进你们的理解。
下面贴一个代码。冒泡排序很重要,几乎每一年matlab比赛都会考,你们懂我意思了吧。(疯狂暗示)
clc;clear;
a=input('请输入一个一维数组a:');
len=length(a);temp=0;
%外层循环控制趟数,内层循环控制比较次数
%一共len个数,所以需要比较len-1趟
%每一趟需要与剩下的len-i个数进行比较,所以是len-i次
%这样理解就不会写错了,不需要死记硬背。
for i=1:len-1
for j=1:len-i
if a(j)>a(j+1)
temp = a(j);
a(j) = a(j+1);
a(j+1)=temp;
end
end
end
disp('从小到大排序后的数组a为:')
a
2-1
看到这个题目,小朋友你是否有很多问号?是不是感觉很懵?你们是不是看到u,v的值都是0~3,但w却是一个4*4的矩阵,并且题目说下标要从1开始就傻掉了?
害。是这样的。这个式子是一个函数,f是自变量,w是因变量。每个指定f的值都可以对应输出一个w的值,这些值构成w。而题目中Matlab下标从1开始指的是编程的时候要变换形式,不能死板的按照题目编。
让我们梳理一下这个函数的构成。一个累乘,两个累加,外加一个u,一个v,所以这个式子要由5层循环构成,求解顺序如下:
1.解决一下这个式子和Matlab编程下标不一致的问题
把原式化为:(数值带入也可)这一步主要靠个人理解,多琢磨
w(u,v)=N1x=1∑Ny=1∑Nf(x,y)i=1∏n(−1)[bi(x)bn−i+1(u)+bi(y)bn−i+1(u)]
2.先写出bi(z)在这个题的所有情况
如果要想解决第一层的累乘,那么bi(z)很重要。主要是对bi(z)定义的理解。当z=6(二进制为110),则b0(z)=0,b1(z)=b2(z)=1。这句话很重要。我们可理解为b数组是某个数的二进制反过来存取后的结果。比如3(10)=011(2),而b数组正好是倒过来,依次为1,1,0。如下表所示。括号内数字代表十进制,括号外为对应二进制。
i\z | 000 (0) | 001(1) | 010(2) | 011(3) |
0 | 0 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 1 |
2 | 0 | 0 | 0 | 0 |
好,bi(z) 我们现在求出来了,那么紧接着就是第三步。
3.求连乘
prod=i=1∏n(−1)[bi(x)bn−i+1(u)+bi(y)bn−i+1(u)]
4.求先与连乘结果相乘,再计算累加
s=x=1∑Ny=1∑N[f(x,y)p]
5.这一步就很简单了,与N1相乘即可
w(u,v)=Ns
求完了。(小问号们,你们现在还有很多朋友了吗?应该没了吧)
代码
clc;
clear;
n=2;
f=repmat([2 3 3 2],4,1)
b=[0 1 0 0;0 0 1 1;0 0 0 0];
a=1;
w=zeros(4);s=0;
for u=1:4
for v=1:4
for x=1:4
for y=1:4
for i=1:2
a=a*(-1)^(b(i,x)*b(n-i+1,u)+b(i,y)*b(n-i+1,u));
end
s=s+f(x,y)*a;
end
end
w(u,v)=0.25*s;
end
end
w