Categories
不学无术 木有技术

[转载]跟我一起写 Makefile

本文来源:

http://www.chinaunix.net/old_jh/23/408225.html

 
陈皓
概述
——
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。

Categories
不学无术

1056. Mice and Rice (25)

时间限制
30 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
========
Mice and Rice is the name of a programming contest in which each programmer must write a piece of code to control the movements of a mouse in a given map. The goal of each mouse is to eat as much rice as possible in order to become a FatMouse.

Categories
不学无术 木有技术

浅谈PCA 人脸识别

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://leen2010.blogbus.com/logs/124631640.html

前几天讨论班我讲了基于PCA的人脸识别,当时我自己其实也只是知道这个算法流程,然后基于该算法利用c++实现了,效果还不错。后来跟师兄一起讨论的时候,才发现这个PCA还是有相当深刻的意义。
PCA的算法:矩阵C=AAT,A的每一列是一张人脸注(将一张人脸图片用一个列向量表示,即对于128*128的图片,将视为16384维的列向量),A的列数就是图片的张数。算法就是求矩阵C的特征向量,每个向量称之为特征脸[1]。为了简单,只取其中部分的特征向量,这些特征向量对应于某些特征值,通常是前M个大的特征值。这样便得到了M个特征向量。接下来就是将每张图片在这M个特征向量上做投影,得到一个M维的权重向量w=(w1,…wM),一个人可能有多张图片,于是将对应于这个人的权重向量做一个平均作为这个人的权重向量。然后对于每个新来的人脸,先求得一个权重向量,然后与人脸库中每个人的权重向量做比较,如果小于某个阈值,则认为他是人脸库中的这个人;否则视为unknown。当然,文章中还给出了另外一个判断一张图像是否是人脸的方法,这里不再讨论。对于计算的时候我们实际上求的是ATA,至于二者的关系,可以参考文章[1],因为与后面讨论的关系不大,这里不细说了。
有个上述简介,我们就大概知道了PCA到底是怎么做的了。刨根问底一下,C到底是什么,C的特征向量又到底是什么,对应于特征值大的特征向量有有什么意义。
1.C到底是什么?我们先看一下C的(i,j)元素是什么。很简单,就是A的第i行与AT的第j列的乘积。那么A的第i行又是什么呢?就是每张图片的第i个像素构成的一个向量。则C的(i,j)元素就是每张图片的第i个像素构成的向量与每张图片的第j个像素构成的向量的乘积。回忆一下概率论中的协方差cov(x,y)=E((x-x–)(y- y–)),这里x– 是x的平均。如果我们把图片的第i个像素视为一个随机变量Xi,那么人脸库中的每张人脸的第i个像素的取值即为这个随机变量的所有取值。根据注,A的第i行的每个值都已经减去了Xi的均值,因此C的(i,j)元素就是随机变量Xi与Xj的协方差。到此,我们已经知道C是什么了。
2.C的特征向量是什么。我们知道对C求特征向量是找到一个可逆矩阵Q,使得Q-1CQ是一个对角阵D,D的元素即为特征值,Q中的每一列即为特征向量,与特征值所在的列一一对应。注意,因为C是实对称阵,故必然可以对角化。由于C是对称的,C的特征向量是正交的,因此Q便是一个正交阵,故Q-1即为QT。先从简单的角度来看,假设C已经是一个对角阵了,并且对角元素依次递减。即随机变量Xi与Xj(i!=j)时是不相关的,而Xi的方差则随着i的增大而减小。也就是前几个像素是方差比较大的像素,即在第一个像素上,每张图片的值变化最大,第二个像素次之,依此类推。举个例子,假设第一个像素表示人脸的额头上的某个点(也许你会问,第一个像素不是图片的最左上角的那个像素吗?为什么会是额头上的某个点,后面会说明为什么可以这么假设),而在这个点上,有些人有痣,有些人没有,那么这一点的方差就会比相邻的额头上的其他点大,因为其他点上,每个人的额头都差不多,因此其像素值也差不多,方差就小了。现在来考虑QTAATQ=D,这里依然假设D中的元素依次递减。对于QTA,QT的每一行是一个特征向量,QT的第i行与A的每一列相乘得到QTA的每一行,从矩阵的角度也可以看作是用QT对A做一个变换。记住这里的QTA可以看做前面讨论的A,那么变换的结果就是使得QTA前面的行对应的是方差大的像素,而且这个变换会把方差最大的放到了第一行(因为D的降序排列),这里也就解释了为什么前面那个例子可以认为第一个像素是额头上的某个点,因为做了变换。我们选择了QT的前M行作为特征向量,因为他们对应了前M个大的特征值。这里可以举一个直观但是不一定恰当的例子,人的头发部分对应的那些像素,经过QT变换后回到某个像素上,那么这个像素会是QTA中的哪个位置呢,我认为应该是QTA的列中靠下面的像素,因为在头发这个像素的地方每个人基本都是头发(这句话很别扭,我是想说,对于比较正规的人脸库,即每张人脸不会有太大的变化,某个人头发的对应的那几个像素对于其他人来说也都是头发,因此变换后这个像素对于每个人都差不多,方差小,固然会在比较靠后的位置了)。QTA的每一列的前M个元素对应的就是每张人脸的权重向量w。因此每张人脸的权重向量的同一个分量可以看作是新的像素,这些新的像素对应着方差依次减小的像素。对于一张新来的人脸,让他在特征向量上作投影得到权重向量,在这些方差大的像素处,如果跟某个人的比较接近,则认为是这个人,这个也是合理的。至此,也许没能讲清楚特征向量是什么,但我想对应于特征值大的特征向量有什么意义这一点也交代的差不多了。
3.2中交代了说了,这里想不到有什么需要补充的了。
理解了这几个问题之后,PCA简洁明了(这本来就是的)而又有深刻意义了。我突然发现原来看似简单的理论其实水深的很,o(︶︿︶)o !我看文章实在是不够认真,如果没有师兄提问,估计我也不会去想这个问题。再次感谢WF师兄。
 
[1]Eigenfaces for Recognition. Matthew Turk,Alex Pentland 1991
注:A的每一列是一张人脸,这里的人脸是每张人脸减去了所有人脸的平均后的人脸

Categories
不学无术

1019. General Palindromic Number (20)

A number that will be the same when it is written forwards or backwards is known as a Palindromic Number. For example, 1234321 is a palindromic number. All single digit numbers are palindromic numbers.
Although palindromic numbers are most often considered in the decimal system, the concept of palindromicity can be applied to the natural numbers in any numeral system. Consider a number N > 0 in base b >= 2, where it is written in standard notation with k+1 digits ai as the sum of (aibi) for i from 0 to k. Here, as usual, 0 <= ai < b for all i and ak is non-zero. Then N is palindromic if and only if ai = ak-i for all i. Zero is written 0 in any base and is also palindromic by definition.
Given any non-negative decimal integer N and a base b, you are supposed to tell if N is a palindromic number in base b.
Input Specification:
Each input file contains one test case. Each case consists of two non-negative numbers N and b, where 0 <= N <= 109 is the decimal number and 2 <= b <= 109 is the base. The numbers are separated by a space.
Output Specification:
For each test case, first print in one line “Yes” if N is a palindromic number in base b, or “No” if not. Then in the next line, print N as the number in base b in the form “ak ak-1 … a0“. Notice that there must be no extra space at the end of output.
Sample Input 1:

27 2

Sample Output 1:

Yes
1 1 0 1 1

Sample Input 2:

121 5

Sample Output 2:

No
4 4 1

===========================
最近产量太低,都是有小bug的答案,唯独这道题终于。。。。
其实这道题相当简单,不想说啥了
时间空间都没有限制,如果机试碰到这种题,那估计是八辈子修来的福。。。
直接贴答案吧。。
===========================

#include 
using namespace std;
long resultSize = 0;
const int MAX_BUFF_SIZE = 30;
int buff[MAX_BUFF_SIZE];
void calcBase(long inputVal, long base)
{
	//计算以base为低的inputVal的值
	if(inputVal == 0)
	{
		resultSize = 1;
		buff[0] = 0;
		return;
	}
	resultSize = 0;
	while(inputVal > 0)
	{
		buff[resultSize++] = inputVal % base;
		inputVal /= base;
	}
}
bool isPalindrome()
{
	long limit = resultSize /2;
	for(long i=0; i> a >> b;
	calcBase(a, b);
	if( isPalindrome())
		cout << "Yes" << endl;
	else
		cout << "No" << endl;
	while(--resultSize)
	{
		cout << buff[resultSize] << " ";
	}
	cout << buff[0];
	return 0;
}
Categories
不学无术

vi 操作笔记

本文转载自:
http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/10/14/2211202.html
======================================
1.关于退出

:wq!  ----强制保存退出
:wq  ---- 保存退出
:x   ----- 作用和:wq 一样
ZZ  ---- 作用和:wq一样,(注意Z是大写的,并且不是在命令模式)
:q  ---- 退出
:q!  ---  强制退出

 
==============================================
2.关于移动
h : 在当前行向左移动一个字符
j:  移动到下一行
k:  移动到上一行
l:  在当前行向右移动一个字符
Ctrl +f:  向前滚动一页
Ctrl +b:  向后滚动一页
:n   将光标定位到第n行
:$   将光标定位到最后一行
0   将光标定位到本行的行首
$   将光标定位到本行的行尾
G   将光标定位到本文章的最后一行,与:   $功能相同。
H   将光标定位到屏幕的顶端
M   将光标定位到屏幕的中间
L   将光标定位到屏幕的底端
============================================
3.关于搜索
/:   后面跟要查找的东西,在文件中向前搜索
?:  后面跟要查找的东西,在文件中向后搜索
n:  向前重复搜索
N:  向后重复搜索
=============================================
4.关于复制
yy:  复制光标当前行
nyy:  复制光标当前行到当前行以下的n-1行
:1,100 co 200   将1~100的内容复制到第200行。
:100,102 co $   将100~102行的内容复制到最后一行。
==============================================
5.关于粘贴
p :   粘贴到当前行的下一行
P(大) :   粘贴到当前行的 上一行
==============================================
6.关于删除.剪切

dd   删除当前行
ndd   与nyy相似
dw   删除一个单词
ndw   与ndd相似
x    删除一个字符
nx   删除n个字符
dG   删除当前光标到文件末尾的所有内容。
d0   删除当前光标到本行行首的所有内容
d$   删除当前光标到本行行尾的所有内容
:1,100d  删除1~100
:100d    删除第100行
:1,100 mo $   将1~100行的内容移动到最后一行。
=============================================
7.关于插入
i:  在当前位置的字符前面进入插入模式
I:  在当前行的开头进行插入
a:  在当前位置的字符后面进入插入模式
A:  在当前行的结尾进行插入
o:  在当前行下面打开一个新行进行插入
O:  在当前行上面打开一个新行进行插入
=============================================
8.关于撤销
 
u:  撤销上一次的更改
=============================================
9.关于替换
regexp:  是要匹配的式样
replacement:  是要替换的字符串
:s/regexp/replacement   ————————-替换当前行出现的第一个式样
:s/regexp/replacement/g  ————————-替换当前行所有的匹配
:%s/regexp/replacement/g  ———————–替换文件中所有匹配式样
=============================================
PS:  还有一个重要的命令就是”.” 命令,这个命令是用来重复上一命令的
 
vi里如何:撤销上次操作?,多次重复一组编辑操作?…….
 
a)   撤消上一个编辑操作。       ====>   u
b)   重复上一个编辑操作。     =====>   .
c)   还原被撤消的编辑操作。   ======>   Ctrl   +   R
d)   多次重复一组编辑操作。 ====>  “. ” 命令可以重复最近一次的编辑动作.
 
 

 
 
 
 

《鸟哥的Linux私房菜》vi 讲义

 

Categories
木有技术

如何在 VPS 上搭建 PPTP/L2TP VPN 简易教程

首先是L2TP的,来自http://www.kukaka.org/home/content/640

如之前所说,PPTP 类的 VPN 可以在 iPhone 手机上使用,但是不能在 Mac OS X 电脑系统上使用,于是,我需要使用 L2TP/IPSec (L2TP over IPSec,即在 IPSec 上搭建 L2TP) 类的 VPN。
这篇文章将介绍如何在 VPS (Xen)上搭建 L2TP/IPSec 类的 VPN,而你只需要一个 VPS 和一台可以上网的电脑。和 PPTP 的一样,L2TP/IPSec 的操作步骤也是基于 Mac 电脑的终端应用程序,对 Linux 系统来讲,步骤几乎是一模一样的,而对 Windows 用户来讲,则需要先安装一个叫 Putty 的软件。
顺便提一下,Xen VPS 的 Ubuntu 系统最好使用 11.04 版本的,因为其他较低的版本(例如 10.04)很可能不行。
 

I、连接 VPS

打开终端应用程序并输入以下命令:
ssh [email protected]
记得将 “xxx.xxx.xxx.xxx” 替换成 VPS 的 IP 地址,例如 “178.18.17.30”,然后回车就可以了。
P.S.:
如果在连接的过程中遇到问题,可以参考之前的 PPTP 教程。

II、安装 OpenSwan

虽然你可以通过输入 “aptitude install openswan” 命令直接安装 OpenSwan,但根据我分别在两个不同的 VPS 上测试的结果,这种方法已经无效,所以,最好还是直接从 OpenSwan 官方网站下载再安装,具体方法如下:

1、输入以下命令:

aptitude install build-essential
回车,输入 “y”,再回车。

2、输入以下命令:

aptitude install libgmp3-dev gawk flex bison
回车,输入 “y”,再回车。

3、输入以下命令:

wget http://www.openswan.org/download/openswan-2.6.35.tar.gz
回车。

4、输入以下命令:

tar xzvf openswan-2.6.35.tar.gz
回车。

5、输入以下命令:

cd openswan-2.6.35
回车。

6、输入以下命令:

make programs
回车。

7、输入以下命令:

make install
回车。到此,OpenSwan 就安装成功了。
备注:
a、2.6.35 是目前最新的版本,将来你可以访问 OpenSwan 官方网站看看有没有更新的版本,如有,不妨尝试一下。
b、文章中的所有命令都可以直接复制粘贴到终端应用程序。

III、编辑 IPSec

OpenSwan 是用来建 IPSec 的,而 IPSec 是用来建 L2TP 的。

1、输入以下命令:

vi /etc/ipsec.conf
回车,输入 “dG” 删除所有内容,按 “i” 键,然后复制并粘贴以下内容:
version 2.0
config setup
    nat_traversal=yes
    virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v6:fd00::/8,%v6:fe80::/10
    oe=off
    protostack=netkey
conn %default
    forceencaps=yes
conn L2TP-PSK-NAT
    rightsubnet=vhost:%priv
    also=L2TP-PSK-noNAT
conn L2TP-PSK-noNAT
    authby=secret
    pfs=no
    auto=add
    keyingtries=3
    rekey=no
    ikelifetime=8h
    keylife=1h
    type=transport
    left=YOUR.VPS.IP.ADDRESS
    leftprotoport=17/1701
    right=%any
    rightprotoport=17/%any
记得将 YOUR.VPS.IP.ADDRESS 替换成自己 VPS 的 IP 地址,例如 178.18.17.30。替换方法如下:
按下”ESC” 键退出插入模式,将光标移到 “Y” 字母上,接着按下 “i” 键,输入 IP 地址,再按一下 “ESC” 键,并将光标移到 “YOUR.VPS.IP.ADDRESS” 上,然后按下 “x” 键把它们全部删除。或者你可以先把内容粘贴到记事本之类的编辑器上并修改好之后再复制粘贴到终端应用程序。
完了之后,输入 “:wq” 并回车保存所做的修改。
备注:
在 Vi 编辑模式下,你需要按 “i” 才能插入内容,完了之后,要按 “ESC” 退出插入模式和保存。

2、输入以下命令:

vi /etc/ipsec.secrets
回车,按 “i” 键并输入以下内容:
YOUR.VPS.IP.ADDRESS %any: PSK “YourSharedSecret”
例如:
178.18.17.30 %any: PSK “123456abcdef”
(小技巧:你需要按 Tab 键创建不同数值之间的空格。)
按 “ESC” 键,输入 “:wq”,再回车保存。

3、一行一行地输入以下命令:

for each in /proc/sys/net/ipv4/conf/*
do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
done
每一行都要回车。

4、输入以下命令:

service ipsec restart
回车。
备注:
输入 “ipsec verify”,回车,如果一切正确,你将会看到如下图所示的结果:
如果不是,则需要重新检查之前的操作步骤,特别是 “ipsec.conf” 的内容。

IV、安装 L2TP

基于 IPSec 的 L2TP 就是 VPN 了。

1、输入以下命令:

cd ..
回车以便进入 VPS 根目录。

2、输入以下命令:

aptitude install xl2tpd
回车,输入 “y”,再回车。

3、输入以下命令:

vi /etc/xl2tpd/xl2tpd.conf
回车,输入 “dG” 删除所有的内容,按下 “i” 键,然后粘贴以下内容:
[global]
; listen-addr = 192.168.1.98
[lns default]
ip range = 10.1.1.2-10.1.1.255
local ip = 10.1.1.1
require chap = yes
refuse pap = yes
require authentication = yes
name = LinuxVPNserver
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
按下 “ESC” 键,输入 “:wq”,并回车保存。

V、创建 xl2tpd

这里假设你的 VPS 已经支持 PPP,如果没有,先输入 “aptitude install ppp” 命令安装 PPP。

1、输入以下命令:

vi /etc/ppp/options.xl2tpd
回车,按下 “i” 键,然后粘贴以下内容:
require-mschap-v2
ms-dns 8.8.8.8
ms-dns 8.8.4.4
asyncmap 0
auth
crtscts
lock
hide-password
modem
debug
name l2tpd
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4
按下 “ESC” 键,输入 “:wq”,并回车保存。
备注:
你可以将 8.8.8.8 和 8.8.4.4 替换成 208.67.222.222 和 208.67.220.220。

2、输入以下命令:

vi /etc/ppp/chap-secrets
回车,按下 “i” 键,并输入如下内容:
username l2tpd password *
例如:
freenuts l2tpd 123456 *
记得用 “tab” 键输入空格,用 “:wq” 保存文件。

3、输入以下命令:

service xl2tpd restart
回车。

VI、IP 转发

这个步骤将使你的 VPN 连接整个互联网。

1、输入以下命令:

vi /etc/sysctl.conf
回车,找到 “#net.ipv4.ip_forward=1” 这一行,接着按 “x” 键删除 “#” 号,然后输入 “:wq” 保存。

2、使转发生效:

sysctl -p
回车,如果一切正常,你将会只看到以下结果:
net.ipv4.ip_forward = 1

3、输入以下命令:

iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o eth0 -j MASQUERADE
回车之后,你就可以连接自己的 L2TP/IPSec VPN 翻墙了,但是如果你重启 VPS 的话,就需要重新执行一次 iptables 命令,并重启 ipsec,为了避免这些,你只需要输入以下命令:
vi /etc/rc.local
并在 “exit 0” 这一行之前粘贴以下内容就可以了:
for each in /proc/sys/net/ipv4/conf/*
do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
done
iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o eth0 -j MASQUERADE
/etc/init.d/ipsec restart
完了之后,你就可以尽情地享用自己搭建的 L2TP/IPSec VPN 了。
额外收获:
以下是根据上面的教程在 2host 的 Xen VPS 上搭建的 L2TP/IPSec VPN:
Server Address: 178.18.17.30
Account Name: freenuts
Password: 123456
Shared Secret: 123456abcdef
这个 VPN 帐号会免费大概半个月,你可以参考这篇文章 在电脑或者手机上试用。
=====================================================

然后是PPTP的(这种方便一些)

在 Ubuntu 上搭建 VPN 服务器的方法非常多,比较著名的有 PPTP, L2TP/IPSec 和 OpenVPN。这里介绍一下pptp的安装配置方法。
服务器环境是单网卡 eth0。
在 Ubuntu 中建立 pptp server 需要的软件包为 pptpd,用 apt-get 即可安装:
sudo apt-get pptpd
安装好后,首先编辑 /etc/pptpd.conf
sudo vi /etc/pptpd.conf
去掉文件最末端的 localip 和 remoteip 两个参数的注释,并进行相应修改。这里,localip 是 VPN 连通后服务器的 ip 地址,而 remoteip 则是客户端的可分配 ip 地址。
localip 10.100.0.1
remoteip 10.100.0.2-10
编辑好这个文件后,我们需要编辑 /etc/ppp/pptpd-options 文件,我们只需要改变其中的 ms-dns 选项,为 VPN 客户端指派 DNS 服务器地址:
ms-dns 202.113.16.10
ms-dns 208.67.222.222
修改 /etc/ppp/chap-secrets 文件,这里面存放着 VPN 的用户名和密码,根据你的实际情况填写即可。如文件中注释所示,第一列是用户名,第二列是服务器名(默认写 pptpd 即可,如果在 pptpd-options 文件中更改过的话,注意这里保持一致),第三列是密码,第四列是 IP 限制(不做限制写 * 即可)。
全部搞定后,我们需要重启 pptpd 服务使新配置生效:
sudo /etc/init.d/pptpd restart
找一台 Windows 电脑,新建个 VPN 链接,地址填服务器的 IP(或域名),用户名密码填刚才设置好的,域那项空着(如果你在 pptpd-options 中设置了,这里就保持一致),点连接就可以了。正常情况下您应该能够建立与服务器的 VPN 链接了。
建立连接之后,您会发现除了可以访问服务器的资源,其余内外和互联网的内容均无法访问。如果需要访问这些内容的话,我们还需要进一步设置:
首先,开启 ipv4 forward。方法是,修改 /etc/sysctl.conf,找到类似下面的行并取消它们的注释:
net.ipv4.ip_forward=1
然后使新配置生效:
sudo sysctl -p
有些时候,经过这样设置,客户端机器就可以上网了(我在虚拟机上这样操作后就可以了)。但我在实验室的服务器上这样操作后仍然无法访问网络,这样我们就需要建立一个 NAT。这里我们使用强大的 iptables 来建立 NAT。首先,先安装 iptables:
sudo apt-get intall iptables
装好后,我们向 nat 表中加入一条规则:
sudo iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
这样操作后,客户端机器应该就可以上网了。
但是,只是这样,iptables 的规则会在下次重启时被清除,所以我们还需要把它保存下来,方法是使用 iptables-save 命令:
sudo iptables-save > /etc/iptables-rules
然后修改 /etc/network/interfaces 文件,找到 eth0 那一节,在对 eth0 的设置最末尾加上下面这句:
pre-up iptables-restore < /etc/iptables-rules
这样当网卡 eth0 被加载的时候就会自动载入我们预先用 iptables-save 保存下的配置。
到此,一个 VPN Server/Gateway 基本就算架设完毕。当然,也许你按照我的方法做了,还是无法成功,那么下面总结一些我碰到的问题和解决方案:
无法建立 VPN 连接
安装好 pptpd 并设置后,客户端还是无法建立到服务器的连接。造成的原因可能有以下几种:
1. 服务器端的防火墙设置:PPTP 服务需要使用 1723(tcp) 端口和 gre 协议,因此请确保您的防火墙设置允许这两者通行。
2. 如果服务器在路由器后面,请确保路由器上做好相应的设置和端口转发。
3. 如果服务器在路由器后面,那么请确保你的服务器支持 VPN Passthrough。
4. 如果客户端在路由器后面,那么客户端所使用的路由器也必须支持 VPN Passthrough。其实市面上稍微好点的路由器都是支持 VPN Passthrough 的,当然也不排除那些最最最便宜的便宜货确实不支持。当然,如果你的路由器可以刷 DD-Wrt 的话就刷上吧,DD-Wrt 是支持的。
能建立链接,但“几乎”无法访问互联网
这里我使用“几乎”这个词,是因为并不是完全不能访问互联网。症状为,打开 Google 搜索没问题,但其它网站均无法打开;SSH 可用,但 scp 不行;ftp 能握手,但传不了文件。我就遇到了这种情况,仔细 Google 后发现原来是 MTU 的问题,用 ping 探测了一下果然是包过大了。知道问题就好办了,我们可以通过 iptables 来修正这一问题。具体原理就不讲了,需要的自己 Google。这里只说解决方案,在 filter 表中添加下面的规则:
sudo iptables -A FORWARD -s 10.100.0.0/24 -p tcp -m tcp –tcp-flags SYN,RST SYN
-j TCPMSS –set-mss 1200
上面规则中的 1200 可以根据你的实际情况修改,为了保证最好的网络性能,这个值应该不断修改,直至能保证网络正常使用情况下的最大值。
好了,至此,一台单网卡 pptp-server 就算完成了。
这篇来自http://www.study365.org/linux/30.html
=====================================================
附加教程:

Ubuntu搭建VPN服务器pptpd安装配置http://www.study365.org/linux/30.html

centos 5搭建vpn服务器请访问http://www.study365.org/linux/60.html

Categories
不学无术

Sleeping barber problem (睡觉的理发师问题)

今天做操作系统作业碰到的问题,一时想不出怎么做,后来Google了一下发现是个经典问题。
=========================================================================
以下英文内容转载自:http://www.answers.com/topic/sleeping-barber-problem
本人的理解继续往下看。
In computer science, the sleeping barber problem is a classic inter-process communication and synchronization problem between multiple operating system processes. The problem is analogous to that of keeping a barber working when there are customers, resting when there are none and doing so in an orderly manner.
The analogy is based upon a hypothetical barber shop with one barber. The barber has one barber chair and a waiting room with a number of chairs in it. When the barber finishes cutting a customer’s hair, he dismisses the customer and then goes to the waiting room to see if there are other customers waiting. If there are, he brings one of them back to the chair and cuts his hair. If there are no other customers waiting, he returns to his chair and sleeps in it.
Each customer, when he arrives, looks to see what the barber is doing. If the barber is sleeping, then the customer wakes him up and sits in the chair. If the barber is cutting hair, then the customer goes to the waiting room. If there is a free chair in the waiting room, the customer sits in it and waits his turn. If there is no free chair, then the customer leaves. Based on a naïve analysis, the above description should ensure that the shop functions correctly, with the barber cutting the hair of anyone who arrives until there are no more customers, and then sleeping until the next customer arrives. In practice, there are a number of problems that can occur that are illustrative of general scheduling problems.
The problems are all related to the fact that the actions by both the barber and the customer (checking the waiting room, entering the shop, taking a waiting room chair, etc.) all take an unknown amount of time. For example, a customer may arrive and observe that the barber is cutting hair, so he goes to the waiting room. While he is on his way, the barber finishes the haircut he is doing and goes to check the waiting room. Since there is no one there (the customer not having arrived yet), he goes back to his chair and sleeps. The barber is now waiting for a customer and the customer is waiting for the barber. In another example, two customers may arrive at the same time when there happens to be a single seat in the waiting room. They observe that the barber is cutting hair, go to the waiting room, and both attempt to occupy the single chair.
The Sleeping Barber Problem is often attributed to Edsger Dijkstra (1965), one of the pioneers in computer science.
Many possible solutions are available. The key element of each is a mutex, which ensures that only one of the participants can change state at once. The barber must acquire this mutex exclusion before checking for customers and release it when he begins either to sleep or cut hair. A customer must acquire it before entering the shop and release it once he is sitting in either a waiting room chair or the barber chair. This eliminates both of the problems mentioned in the previous section. A number of semaphores are also required to indicate the state of the system. For example, one might store the number of people in the waiting room.
A multiple sleeping barbers problem has the additional complexity of coordinating several barbers among the waiting customers.

Implementation

  • The following pseudocode guarantees synchronization between barber and customer and is deadlock free, but may lead to starvation of a customer. The functions wait() and signal() are functions provided by the semaphores.
# The first two are mutexes (only 0 or 1 possible)
Semaphore barberReady = 0
Semaphore accessWRSeats = 1     # if 1, the # of seats in the waiting room can be incremented or decremented
Semaphore custReady = 0         # the number of customers currently in the waiting room, ready to be served
int numberOfFreeWRSeats = N     # total number of seats in the waiting room
def Barber():
  while true:                   # Run in an infinite loop.
    wait(custReady)             # Try to acquire a customer - if none is available, go to sleep.
    wait(accessWRSeats)         # Awake - try to get access to modify # of available seats, otherwise sleep.
    numberOfFreeWRSeats += 1    # One waiting room chair becomes free.
    signal(barberReady)         # I am ready to cut.
    signal(accessWRSeats)       # Don't need the lock on the chairs anymore.
    # (Cut hair here.)
def Customer():
  while true:                   # Run in an infinite loop to simulate multiple customers.
    wait(accessWRSeats)         # Try to get access to the waiting room chairs.
    if numberOfFreeWRSeats > 0: # If there are any free seats:
      numberOfFreeWRSeats -= 1  #   sit down in a chair
      signal(custReady)         #   notify the barber, who's waiting until there is a customer
      signal(accessWRSeats)     #   don't need to lock the chairs anymore
      wait(barberReady)         #   wait until the barber is ready
      # (Have hair cut here.)
    else:                       # otherwise, there are no free seats; tough luck --
      signal(accessWRSeats)     #   but don't forget to release the lock on the seats!
      # (Leave without a haircut.)

============================

本人观点:
其中需要共享的数据应该只有可用的座椅数目(numberOfFreeWRSeats),但是需要改动这个座椅数目的过程比较繁杂…原本以为N是用作信号量里面的,但是这个解决方案来看是把他作为额外的变量。
为什么N不能做信号量?后来想了一下..这个东西是共享的资源…明显不能拿来做信号量的吧。
文中3个信号量

Semaphore barberReady = 0
Semaphore accessWRSeats = 1     # if 1, the # of seats in the waiting room can be incremented or decremented
Semaphore custReady = 0         # the number of customers currently in the waiting room, ready to be served

其中barberReady是理发师就绪的信号量,barber讲客人请入理发室后,signal一下,然后示意客户可以开始理发了,客户那边wait这个信号量,等到了就开始理发过程。这个是一个同步的关系,因为肯定是要理发师先准备好,然后客人才可以开始理发,这两个动作有顺序要求,所以信号量初值设置成0.
第二个accessWRSeats是用来锁座椅数目改变的,锁住(=0)的时候,说明waitingroom内有人员变动中,要阻塞其他人对人员变动的尝试。显然这是一个互斥量(mutex),当客人进入理发室准备理发时、或者理发店外有人进入时,都要改变numberOfFreeWRSeats这个量,这种操作显然是独占的,同时只能有一方来修改这个值,所以引入此信号量协调。
第三个嘛..客人就绪的信号量,主要原因是barber空闲下来的时候需要睡大觉。这个与第一个信号量一样,是一个同步的问题。即客人先要准备好了,才能把理发师唤醒做事情,不然就别吵到他。
三个信号量理解了,后面的过程也就一目了然了。不知道我说的对不对…
这个问题应该有另一(或多)种解法,另一种解法是指会导致barber的starvation的解法,或者是权衡两者折中的办法,这个没有多想过。

Categories
不学无术 木有技术

【Android Camera】之 Preview

本文转载自:

http://blog.csdn.net/yiyaaixuexi/article/details/6455741

================================================================
实在不好复制过来,去原文看吧。

Categories
木有技术

ThinkPad RnR 系统恢复盘 IMD IMZ 文件解压密码表

本文转载自:
http://forum.51nb.com/thread-1343052-1-1.html
=================================
ThinkPad RnR 系统恢复盘 IMD IMZ 文件解压密码表

ENCYPTED DECRYPTED PASSWORD
BMGR be0d
HURRICANES xwbdbgmlbu
HUURICANES xwvdbgmlbu
STANLEYCUP u1kmkblhvi
TVTPASS 2b0ilsu
CKD158A iqyrabm
CKD164T iqyrhk2
CKD170T iqyrzm2
CKD171A iqyrzpm
CKD173T iqyrzd2
CKD174T1 iqyrzk2q
CKD179T iqyrzs2
CKD185T1 iqyrc`2q
CKD192T iqyrtj2
CKD196T iqyrtg2
CKD197T iqyrty2
CKD199T iqyrts2
CKD204A iqylnkm
CKD205T iqyln`2
BKD010F bqyoqmu
BKD023F bqyokdu
BKD0025F bqyonjbt
BKD037A bqyoeym
BKD047F bqyolyu
CM2ZCFR iejfhsd
以上是已被别人解开的密码,
以下是别人通过以上密码绘制的对应图表:

Thinkpad RnR 系统恢复盘 密码表
Thinkpad RnR 系统恢复盘 密码表

以下是我通过上面的对应图表列出的X60 7CD XP恢复盘文件的密码,成功解压无误。
2GLGU31_  ickb1bdc
3GZUM0A0  fljbcbdk
CKD158A   iqyrabm
CKD1642   iqyrhkl
CKD1702   iqyrzml
CKD171A   iqyrzpm
CKD1732   iqyrzdl
CKD17421  iqyrzklq
CKD1792   iqyrzsl
CKD1852   iqyrc`l
CKD1922   iqyrtjl
CKD1962   iqyrtgl
CKD1972   iqyrtyl
CKD1992   iqyrtsl
CKD204A   iqylnkm
XM2AACS   rejmlgu
XM2UACS   rejxlgu
TVTPASS   2b0ilsu
图表来自“http://forum.notebookreview.com/ … vice-partition.html”
向那些神人致敬!

Categories
不学无术 木有技术

1042. Shuffling Machine (20)

Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techniques are seen as weak, and in order to avoid “inside jobs” where employees collaborate with gamblers by performing inadequate shuffles, many casinos employ automatic shuffling machines. Your task is to simulate a shuffling machine.
The machine shuffles a deck of 54 cards according to a given random order and repeats for a given number of times. It is assumed that the initial status of a card deck is in the following order:
S1, S2, …, S13, H1, H2, …, H13, C1, C2, …, C13, D1, D2, …, D13, J1, J2
where “S” stands for “Spade”, “H” for “Heart”, “C” for “Club”, “D” for “Diamond”, and “J” for “Joker”. A given order is a permutation of distinct integers in [1, 54]. If the number at the i-th position is j, it means to move the card from position i to position j. For example, suppose we only have 5 cards: S3, H5, C1, D13 and J2. Given a shuffling order {4, 2, 5, 3, 1}, the result will be: J2, H5, D13, S3, C1. If we are to repeat the shuffling again, the result will be: C1, H5, S3, J2, D13.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer K (<= 20) which is the number of repeat times. Then the next line contains the given order. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the shuffling results in one line. All the cards are separated by a space, and there must be no extra space at the end of the line.
Sample Input:

2
36 52 37 38 3 39 40 53 54 41 11 12 13 42 43 44 2 4 23 24 25 26 27 6 7 8 48 49 50 51 9 10 14 15 16 5 17 18 19 1 20 21 22 28 29 30 31 32 33 34 35 45 46 47

Sample Output:

S7 C11 C10 C12 S1 H7 H8 H9 D8 D9 S11 S12 S13 D10 D11 D12 S3 S4 S6 S10 H1 H2 C13 D2 D3 D4 H6 H3 D13 J1 J2 C1 C2 C3 C4 D1 S5 H5 H11 H12 C6 C7 C8 C9 S2 S8 S9 H10 D5 D6 D7 H4 H13 C5

===================================
本题目主要难度:英语阅读。
就是数组里面元素换来换去没啥好说的,就是发现自己数组指针这块了解的不是很清晰,以后得注意。
===================================

#include 
#include 
using namespace std;
const int SUFF_SIZE = 54;
int *cards = new int[SUFF_SIZE]; //扑克牌数组
int *results = new int[SUFF_SIZE];
int* suffle(int * src, int* rule)
{
	for(int i=0; i= 10)
	{
		result += "1";
		postfix = postfix%10;
	}
	result += (char)(postfix + 0x30);
	return result;
}
int rules[SUFF_SIZE]; //suffle规则
int main()
{
	int K;
	cin >> K;
	for(int i=0; i> rules[i];
	}
	while(K--)
	{
		suffle(cards, rules);
		for(int i=0; i