2008年4月26日星期六

Mingw下查看所有预定义宏

$ gcc -dM -E - < nul

#define __DBL_MIN_EXP__ (-1021)
#define __FLT_MIN__ 1.17549435e-38F
#define __CHAR_BIT__ 8
#define __WCHAR_MAX__ 65535U
#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
#define __FLT_EVAL_METHOD__ 2
#define __DBL_MIN_10_EXP__ (-307)
#define __FINITE_MATH_ONLY__ 0
#define __GNUC_PATCHLEVEL__ 5
#define _stdcall __attribute__((__stdcall__))
#define __SHRT_MAX__ 32767
#define __LDBL_MAX__ 1.18973149535723176502e+4932L
#define __LDBL_MAX_EXP__ 16384
#define __SCHAR_MAX__ 127
#define __USER_LABEL_PREFIX__ _
#define __STDC_HOSTED__ 1
#define __WIN32 1
#define __LDBL_HAS_INFINITY__ 1
#define __DBL_DIG__ 15
#define __FLT_EPSILON__ 1.19209290e-7F
#define __tune_i686__ 1
#define __LDBL_MIN__ 3.36210314311209350626e-4932L
#define __DECIMAL_DIG__ 21
#define __LDBL_HAS_QUIET_NAN__ 1
#define __GNUC__ 3
#define _cdecl __attribute__((__cdecl__))
#define __DBL_MAX__ 1.7976931348623157e+308
#define __WINNT 1
#define __DBL_HAS_INFINITY__ 1
#define __WINNT__ 1
#define _fastcall __attribute__((__fastcall__))
#define __USING_SJLJ_EXCEPTIONS__ 1
#define __DBL_MAX_EXP__ 1024
#define __WIN32__ 1
#define __LONG_LONG_MAX__ 9223372036854775807LL
#define __GXX_ABI_VERSION 1002
#define __FLT_MIN_EXP__ (-125)
#define __DBL_MIN__ 2.2250738585072014e-308
#define __DBL_HAS_QUIET_NAN__ 1
#define __REGISTER_PREFIX__
#define __cdecl __attribute__((__cdecl__))
#define __NO_INLINE__ 1
#define __i386 1
#define __FLT_MANT_DIG__ 24
#define __VERSION__ "3.4.5 (mingw special)"
#define _WIN32 1
#define _X86_ 1
#define i386 1
#define __i386__ 1
#define __SIZE_TYPE__ unsigned int
#define __FLT_RADIX__ 2
#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
#define __MSVCRT__ 1
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MAX_10_EXP__ 38
#define __LONG_MAX__ 2147483647L
#define __FLT_HAS_INFINITY__ 1
#define __stdcall __attribute__((__stdcall__))
#define __LDBL_MANT_DIG__ 64
#define __WCHAR_TYPE__ short unsigned int
#define __FLT_DIG__ 6
#define __INT_MAX__ 2147483647
#define WIN32 1
#define __MINGW32__ 1
#define __FLT_MAX_EXP__ 128
#define __DBL_MANT_DIG__ 53
#define __WINT_TYPE__ short unsigned int
#define __LDBL_MIN_EXP__ (-16381)
#define __LDBL_MAX_10_EXP__ 4932
#define __DBL_EPSILON__ 2.2204460492503131e-16
#define __tune_pentiumpro__ 1
#define __fastcall __attribute__((__fastcall__))
#define WINNT 1
#define __FLT_DENORM_MIN__ 1.40129846e-45F
#define __FLT_MAX__ 3.40282347e+38F
#define __FLT_MIN_10_EXP__ (-37)
#define __GNUC_MINOR__ 4
#define __DBL_MAX_10_EXP__ 308
#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
#define __PTRDIFF_TYPE__ int
#define __LDBL_MIN_10_EXP__ (-4931)
#define __LDBL_DIG__ 18
#define __declspec(x) __attribute__((x))

2008年4月25日星期五

vc2005 不能调试错误

VC 2005 不能调试 vc2005 无法找到调试信息 未使用调试信息生成二进制文件

其实问题在于,在空项目中不生成调试文件pdb,所以无法调试。
要让项目生成pdb文件,需要更改:
项目属性,configuration properties->linker->Generate Debug Info 从 no 改为 yes

vc2005 不能调试错误

VC 2005 不能调试 vc2005 无法找到调试信息 未使用调试信息生成二进制文件

其实问题在于,在空项目中不生成调试文件pdb,所以无法调试。
要让项目生成pdb文件,需要更改:
项目属性,configuration properties->linker->Generate Debug Info 从 no 改为 yes

vc2005 不能调试错误

VC 2005 不能调试 vc2005 无法找到调试信息 未使用调试信息生成二进制文件

其实问题在于,在空项目中不生成调试文件pdb,所以无法调试。
要让项目生成pdb文件,需要更改:
项目属性,configuration properties->linker->Generate Debug Info 从 no 改为 yes

2008年3月24日星期一

sizeof and -- 测试

#include <stdio.h>

int main()
{
   int a=1;
   a=a-=a--;
  printf("a=%d\n",a);
   int size=sizeof(a=2);
  printf("size=%d a=%d\n",size,a);
  return 0;

}
输出
a=-1;
size=4 a=-1

2008年3月15日星期六

baidu笔试题 IP段问题

Security公司的网络管理工程师Mr. leak最近发现有不少来自公司外部IP的请求,试图非法访问公司内部资源,为了不影响数据访问流程。
他不得不写一个高效的程序――一个工作在Ipv4上的防火墙,如果请求来自非授权的ip地址,则将请求丢弃。为了便于管理,通过文本文件IP.TXT
162.105.91.163
59.66.105.0  59.66.105.255
211.71.0.0  211.71.255.255
限制:IP段的起止地址间以空格隔开。文件不超过10万行,内存不超过4M字节。
要求:请编写一个程序,读入IP.TXT文件。并从标准输入接受一个IP地址。如果该地址在授权范围内,则在标准输出上打印Y,否则打印N.如果输入为一个空行,程序结束。
 请给出思路(文字描述),完成代码,分析你采用算法的优劣。
 请列举测试方法和思路

发信人: Curvelet (小曲线), 信区: Algorithm
标  题: Re: 谈一条网上的百度笔试题
发信站: 水木社区 (Mon Oct 15 20:59:18 2007), 站内

ip 段是可以合并的,
不需要用 trie 或者 interval tree,
用个数组+二分查找即可。

先把 ip 段改写成 ip 区间形式 [ip_a, ip_b],
ip_a 是起始 ip 地址, ip_b 是结束 ip 地址。
现对所有 ip 区间按 ip_a 排序,
扫描一遍排序结果,
合并相交的 ip 区间,
结果存在一个数组中。

对于给定的 ip_c,
用二分查找在数组中找到最大的 ip_a <= ip_c,
然后看 ip_c 是否在查找到的区间中即可。

最多 10万行数据,每行对应两个 ip 共 8 字节,
最多 0.8MB。

ps:以ip_a升序排序,顺序扫描ip_b,并记录ip_b的最大值,若当前项的ip_a>以上ip_b 的最大值,则生成一个区间段,以下类似。
------------------------------------------------------------------------------------------------------------------------
2005年百度之星有道求重叠区间大小的题目,和上面的解题思路类似,上面是求并,这里是求交:

题目描述:请编写程序,找出下面"输入数据及格式"中所描述的输入数据文件中最大重叠区间的大小。
对一个正整数n,如果n在数据文件中某行的两个正整数(假设为A和B)之间,即A<=n<=B或A>=n>=B,则n属于
该行;如果n同时属于行i和j,则i和j有重叠区间;重叠区间的大小是同时属于行i和j的整数个数。
例如,行(10 20)和(12 25)的重叠区间为[12 20],其大小为9;行(20 10)和(12 18)的重叠区间为
[12 18],其大小为7;行(20 10)和(20 30)的重叠区间大小为1。

输入数据:程序读入已被命名为input.txt的输入数据文本文件,该文件的行数在1到1,000,000之间,每行有
用一个空格分隔的2个正整数,这2个正整数的大小次序随机,每个数都在1和2^32-1之间。(为便于调试,
您可下载测试input.txt文件,实际运行时我们会使用不同内容的输入文件。)

输出数据:在标准输出上打印出输入数据文件中最大重叠区间的大小,如果所有行都没有重叠区间,则输出0。

评分标准:程序输出结果必须正确,内存使用必须不超过256MB,程序的执行时间越快越好。

思路:按起点降序排序,扫描一遍,维护当前线段之前的线段对后面造成的最远阴影

代码如下:
#include <stdio.h>
#include <stdlib.h>

struct node{
     unsigned x;
    unsigned y;
}a[1000000];

int compare(const void *a,const void *b)
{
    struct node *da=(struct node*)a;
    struct node *db=(struct node*)b;
    return (da->x)<(db->x);
  }

int main()
{
    unsigned i,j;
    unsigned n=0;
    freopen("qujian.txt","r",stdin);
   while(scanf("%u%u",&i,&j)!=EOF)
  {
    if(i<j)
    {
        a[n].x=i;
        a[n].y=j;
    }  
    else
    {
        a[n].x=j;  
        a[n].y=i;
    }
    n++;
}
    qsort(a,n,sizeof(struct node),compare);  //以x 降序排序
    unsigned max;                                   
    unsigned tmp;                      
     unsigned ans=0;
     max=a[0].y;
    for(i=1;i<n;i++)
    {
      if(a[i].y>max)
       {
         tmp=max;
         max=a[i].y;
      }
   else
        tmp=a[i].y;
   if((tmp-a[i].x+1)>ans)    //以本节点x为起点对后面造成的最远阴影
       ans=tmp-a[i].x+1;
  }
    printf("%u\n",ans);
   return 0;
}

baidu笔试题 数据检索问题 from smth

三、 现有两个文件,

a)数据文件A,格式为:关键词、IP地址、时间
,记录条数为1000万左右,该文件是无序排列的。

b)数据文件B是关键词ID到关键词的对应表文件,格式为:ID、关键词,记录条数在100万左右,也是无序排列的。该对应表中的记录是一一对应的,不存在ID或者关键词重复的情况。

要求将数据文件A对应的关键词替换为B中的ID,生成新的数据文件C,数据文件C的格式为:关键词ID、IP地址、时间。

请设计一个程序,实现上述功能,并分析时间复杂度和空间复杂度。运行程序所使用的服务器的内存为1G,硬盘足够大。(至少要给出关键算法和设计思路)

简评:

如何对海量数据进行快速检索,这是搜索引擎的必需考虑的问题。这又涉及到数
据结构和算法。  因此,要想进入百度,就必须熟悉一些基本的算法和数据结构。
思路及解决方案如下:

1: 设计用TRIE树实现关键词到其对应id的快速词典查找

TRIE树的每一个节点为一个包含256个元素的数组,同时指针指向其下一级节点


节点定义如下:

struct trienode
 {
 int   id;
 struct trienode *child[256];
 }TRIENODE;


如果TRIE树的某个节点的指针为NULL,说明从跟节点到当前节点的路径构成文件
B中的一个关键词,

在其节点的id保存该关键词的id;如果指针不为NULL,则id对应为0或者一个无穷
大的整数,标志从根节点

到当前节点的路径不是一个完整的关键词。

将关键词转化为二进制无符号char型数组,即对于汉字等双字节字符视为两个无
符号char型整数,

每个元素的取值范围在0到255之间。

2:生成文件b的TRIE树

步骤1:依次读取文件b的每一行,对每一行执行步骤2到步骤5

步骤2:读取关键词id和关键词,令为key

步骤3:依次读取key的每一个字符,对每一个字符,执行步骤4
;

步骤4:如果该字符对应的指针为NULL,则创建其儿子节点;

步骤5:为当前节点的对应字符id置为关键词id

3:根据A文件生成C文件

步骤1:依次读取文件A的每一行,对每一行执行步骤2到步骤5

步骤2:分别获取当前行关键词、ip地址和时间

步骤3:令关键词key=c1c2...cm,对c1到cm每个字符,执行步骤4

步骤4:获取根节点的第c1个元素指针,转移到节点node1,

根据node1的第c2个元素指针,转移到node2...

根据nodem的第cm个元素,获取关键词的id

步骤5:往文件c中写入一行数据,格式为关键词的id、ip地址和时间

4:复杂度分析

生成文件B的TRIE树过程时间复杂度为O(n*m),其中n为文件b行数,m为文件b关
键词的最大长度。TRIE的空间复杂度为O(n*m),n和m含义同上,但由于实际应用中关
键词之间可能会有很多前缀相同现象,所以实际耗费空间并不会很高。

生成C文件的时间复杂度同样为O(n*m),n为文件a行数,m为文件a关键词的最大
长度,因为有了TRIE树之后,给定一个关键词获得其id的时间复杂度为关键词长度。
生成C文件的过程除了TRIE树空间外基本不需要太多额外的空间,空间复杂度为O(1)
,由于系统有1G的可用内存,TRIE占用的空间在几十兆到200M之间(与关键词集合有
关),因此本方法完全可行。


2008年3月14日星期五

baidu笔试mp3搜索问题 from smth

四、设计题:35分 共1题
注意:请尽可能详细描述你的数据结构、系统架构、设计思路等
。建议多写一些伪代码或者流程说明。

1.    假设一个mp3搜索引擎收录了2^24首歌曲,并记录了可收听这些歌曲的2^30条URL,但每首歌的URL不超过2^10个。系统会定期检查这些URL,如果一个URL不可用则不出现在搜索结果中。现在歌曲名和URL分别通过整型的SONG_ID和URL_ID唯一确定。对该系统有如下需求:
1)    通过SONG_ID搜索一首歌的URL_ID,给出URL_ID计数和列表
2)    给定一个SONG_ID,为其添加一个新的URL_ID
3)    添加一个新的SONG_ID
4)    给定一个URL_ID,将其置为不可用

限制条件:内存占用不超过1G,单个文件大小不超过2G,一个目录下的文件数不超过128个。

为获得最佳性能,请说明设计的数据结构、搜索算法,以及资源消耗。如果系统数据量扩大,该如何多机分布处理?
:================================================

内存不够存储这些url,所以将数据写入若干个文件中。

每一首歌曲对应的存储在文件中的信息格式为(url1, url2……)。

文件的总大小大约为2^24*2^10*4 =2^36 =64GB.根据SongID即可计算出在哪个文件的哪个位置,那么一个随机的查询操作耗时即是一次随机打开文件啊并执行seek操作读取数据的实际,大约是ms级别。

将每首歌曲的信息存入文件中,由于每首歌的url不超过2^10个,所以在文件中每首歌的存储结构是2^10个int数,每个int数字标识着一个url。-1表示url不存在。初始化时将文件中每个int数初始化为-1.
这样每个SongID对应的信息占用的空间为2^10*4=4KB,设每个文件大小1G,那么每个文件可存储2^18=256K个Song的信息。总共需要64个文件,把这些文件编号从0-63.

对于任意一个SongID,他所对应的url信息所在的文件编号是:SongID>>18,在文件中的位置是:(SongID&0x3FFFF)<<12.

另外内存中用一个2^24大小的short int型数组来保存每一首歌曲对应的url的个数,计数组名为urlCount[],初始化时值为-1,表示对应的Song_ID不存在。此数组占用空间2^25Byte=32MB;

url是否可用的信息用位图来标识。位图保存在内存中,占用的空间为2^30/8=2^27 Byte=128MB.


对所要求的操作:
:1)    通过SONG_ID搜索一首歌的URL_ID,给出URL_ID计数和列表
通过SONG_ID计算出文件号和对应在文件中的位置,从urlCount[]中读取url个数,读出所有的url,并对每个url_ID查询位图看是否可用,若可用,将此url加入返回列表。

:2)    给定一个SONG_ID,为其添加一个新的URL_ID
通过SONG_ID计算出文件号和对应在文件中的位置,设为start,在通过urlCount[]得到url个数,假设有n个url,那么将新的URL_ID写入文件的start+sizeof(int)*n处。修改urlCount[SONG_ID]的值。

:3)    添加一个新的SONG_ID
检查将对应的urlCount[SONG_ID],若为-1,则修改为0,若大于等于0,则表明改Song_ID已经存在。

:4)    给定一个URL_ID,将其置为不可用
修改url位图,标识URL_ID对应的位,表示为不可用。

2008年3月11日星期二

常用字符串Hash函数

// RS Hash Function
unsigned int RSHash(char *str)
{
    unsigned int b=378551;
    unsigned int a=63689;
    unsigned int hash=0;
    while(*str)
    {
        hash=hash*a+(*str++);
        a*=b;
    }
    return (hash & 0x7fffffff);

}

//JS Hash Function
unsigned int JSHash(char *str)
{
    unsigned int  hash=1315423911;
    while(*str)
    {
        hash^=((hash << 5)+(*str++)+(hash>>2));
     }
    return (hash & 0x7fffffff);
}

//P.J Weinberger Hash Function
unsigned int PJWHash(char *str)
{
    unsigned int BitsInUnignedInt=(unsigned int)(sizeof(unsigned int)*8);
    unsigned int ThreeQuarters=(unsigned int)((BitsInunignedInt*3)/4);
    unsigned int OneEighth=(unsigned int)(BitsInUnignedInt/8);
    unsigned int hash=0;
    unsigned int test=0;
    while(*str)
    {
        hash=(hash<<OneEighth)+(*str++);
        if((test=hash & HighBits)!=0)
        {
            hash=((hash^(test>>ThreeQuarters)) & (^HighBits));
         }
    }
    return (hash & 0x7fffffff);
}

//ELF Hash Function
unsigned int ELFHash(char *str)
{
    unsigned int  hash=0;
    unsigned int x=0;

    while(*str)
    {
        hash=(hash<<4)+(*str++);
        if((x=hash & 0xf0000000L)!=0)
        {
            hash^=(x>>24);
            hash &=~x;
        }
    }
    return (hash & 0x7fffffff);
}

//BKDR Hash Function
unsigned int BKDRHash(char *str)
{
    unsigned int seed=131;//31 131 1313 13131 131313 etc..
    unsigned int hash=0;
    while(*str)
    {
        hash=hash*seed+(*str++);
    }
    return (hash & 0x7fffffff);
}

//SDBM Hash Function
unsigned int SDBMHash(char *str)
{
    unsigned int hash=0;
    while(*str)
    {
        hash+=(hash<<5)+(*str++);
    }
    return (hash & 0x7fffffff);
}

//AP Hash Function
unsigned int APHash(char *str)
{
    unsigned int hash=0;
    int i;

    for(i=0;*str;i++)
    {
        if((i&1)==0)
        {
            hash^=((hash<<7)^(*str++)^(hash>>3));
        }
        else
        {
            hash^=(~((hash<<11)^(*str++)^(hash>>5)));
        }
    }
    return (hash & 0x7fffffff);
}

//ELF hash Function比较常用

2008年3月5日星期三

Inline assembly for x86 in Linux

Inline assembly for x86 in Linux

1.Register names are prefixed by %. That is, if eax has to be used, it should be used as %eax.

2.In any instruction, source comes first and destination follows. This differs from Intel syntax, where source comes after destination.

3. An immediate operand is specified by using $.

4. Any indirect references to memory are done by using ( ).

5.GCC provides the special construct "asm" for inline assembly, which has the following format:
 asm ( assembler template
: output operands (optional)
: input operands (optional)
: list of clobbered registers (optional)
);
6.a %eax
b %ebx
c %ecx
d %edx
S %esi
D %edi

7.Memory operand constraint(m)
When the operands are in the memory, any operations performed on them will occur directly in
the memory location, as opposed to register constraints, which first store the value in a
register to be modified and then write it back to the memory location. But register constraints
are usually used only when they are absolutely necessary for an instruction or they significantly
speed up the process. Memory constraints can be used most efficiently in cases where a C
variable needs to be updated inside "asm" and you really don't want to use a register to hold
its value.

2008年3月4日星期二

MMX


第五章 MMX™的编码技术

  本节包括几个简单的例子来帮助你开始编写应用程序,最终目的是提供一些经常使用的、简单的低级操作。每个例子都使用最少的指令数来达到奔腾和P6系统处理器的最佳性能。

  每个例子包括:

  • 一个简短的描述
  • 核心代码
  • 必要的解释

  考虑到你可能会将这些例子插入到更长的代码序列中,故这些例子中不涉及有关调度问题。

5.1 无符号分组

  MMX™技术提供了几条用来将MMX™寄存器中的数据成组和分组的指令。分组指令可用于对一个无符号数进行零扩展(zero-extend)。下例假设源操作数是一个字组数据(16位)类型。

  输入:

	MM0:	源值
MM7: 0

  如果需要,可用一个局部变量代替MM7寄存器。


  输出:

MM0: 由2个低端字数据经零扩展形成的两个32位双字。
MM1: 由2个高端字数据经零扩展形成的两个32位双字。

MOVQ MM1, MM0 ;源数据复制
PUNPCKLWD MM0, MM7 ;将两个低端字数据分组为两个32位双字
PUNPCKHWD MM1, MM7 ;将两个高端字数据分组为两个32位双字

5.2 有符号分组

  当对一个分组时,应对有符号数进行符号扩展(sign-extend)。这一点与上述零扩展不同。下例假设源操作数是一个成组字数据(16位)类型。

  输入:

	MM0:	源值

  输出:

MM0: 由2个低端字数据经符号扩展形成的两个32位双字。
MM1: 由2个高端字数据经符号扩展形成的两个32位双字。

PUNPCKHWD MM1, MM0 ;将源数据的两个高端字数据分组为
;目标数据的第2个和第4个字数据
PUNPCKHLD MM0, MM0 ;将源数据的两个低端字数据分组为
;目标数据的第2个和第4个字数据
PSRAD MM0, 16 ;将源数据的两个低端字数据
;经符号扩展形成的两个32位双字
PSRAD MM1, 16 ;将源数据的两个高端字数据
;经符号扩展形成的两个32位双字

5.3 饱和模式下的交错成组

  PACK指令按预先定义的顺序将两个值合并到目的寄存器。特别说明的是,PACKSSDW指令将源操作数两个有符号双字和目的操作数的两个有符号双字合并成目的寄存器中的四个有符号字。如图5一1所示:



图5-1 PACKSSDW mm, mm/mm64指令示例

  下例将两个值交错送入目的寄存器,如图5一2所示。



图5-2 饱和模式下的交错成组示例

  本例中源操作数为有符号的双字,结果是交错的有符号字。成组指令不论是否是饱和模式都可执行。

  输入:

	MM0:	第一个有符号源值
MM1: 第二个有符号源值

  输出:

MM0: 第一、三字来自MM0中的饱和模式有符号双字,
第二、四字来自MM1中的饱和模式有符号双字。

PACKSSDW MM0, MM0 ;饱和模式有符号成组
PACKSSDW MM1, MM1 ;饱和模式有符号成组
PUNPKLWD MM0, MM1 ;将操作数低端16位值交错

  成组指令总是假设源操作数为有符号数。目的寄存器中的结果由执行操作的成组指令定 义。例如,PACKSSDW指令将两个源数据中各自的两个有符号32位值形成目的寄存器中的四个饱和的16位有符号值。另一方面,PACKUSWB指令将 两个源数据中各自的四个有符号16位值形成目的寄存器中的四个饱和的8位无符号值。有关MMX™指令集的完整说明请见《Intel体系结构MMX™技术程 序员参考手册》(Inte1 Architecture MMX™ Technology Programmers Reference Manual),(序号243007)。

5.4 非饱和模式下的交错成组

  本例除结果字为非饱和的外,同上例相似。另外,为防止溢出,本操作只使用每个双字的低16位。

  输入:

MM0: 有符号源值
MM1: 有符号源值

  输出:

MM0: 第一、三字来自MM0中的双字的低16位,
第二、四字来自MM1中的的双字的低16位。

PSLLD MM1, 16 ;将每个双字值中的LSB移16位
;到MSB位置
PAND MM0, {0, FFFF, 0, FFFF}
;将每个双字值的16MSB标记为0
POR MM0, MM1 ;合并两个操作数

5.5 非交错分组

  分组指令将目的操作数和源操作数的数据元素交错合并到目的寄存器中。下例非交错地 将两个操作数合并到目的寄存器中。例如,从源数据1中的字组数据类型中取两个相邻元素,并将该值放到结果的低32位中。然后从源数据2中的字组数据类型中 取两个相邻元素,并将该值放到结果的高32位中。目的寄存器的一种组合形式如图5一3所示。



图5-3 MM0中的非交错分组的结果

  目的寄存器的另一种相反的组合如图5一4所示。



图5-4 MM1中的非交错分组的结果

  下例将两个字组的源数据按非交错方式分组。其实现方法为用将双字变为四字的指令代替将字变为双字的分组指令。

  输入:

	MM0:	字组源值
MM1: 字组源值

  输出:

MM0: 包含两个非交错的初始源值的低端字
MM2: 包含两个非交错的初始源值的高端字

MOVQ MM2, MM0 ;复制源值1
PUNPCKLDQ MM0, MM1 ;用MMl的两个低端字替换MM0的两个高端字,
;保留MM0中的两个低端字
PUNPCKHDQ MM2, MM1 ;将MM2的两个高端字移到低端,
;将MM1的两个高端字送入MM2的两个高端字

5.6 含有一个常数的复数乘法

  复数的乘法由四个乘法和两个加法构成。PMADDWD正是这样的指令。为了使用该指令,仅需将数据格式化为四个16位值。每个实部和虚部值应为16位值。

  令输入数据为Dr和Di

    这里 Dr=数据的实部
       Di=数据的虚部

  将复数的常系数格式化为内存中的四个16位值[Cr -Ci Ci Cr]。

  记住使用MOVQ指令将值取出送到MMX™寄存器中。

  输入:

MM0: 由Dr,Di构成的复数
MM1: 在格式[Cr -Ci Ci Cr]中的常复数系数

  输出:

MM0: 包含[Pr Pi]的两个32位双字复数,
其实部是由Pr=Dr*Cr-Di*Ci生成,
复数的虚部是由Pi=Dr*Ci+Di*Cr生成。

PUNPCKLDQ MM0,MM0 ;生成[Dr  Di  Dr  Di]
PMADDWD MM0,MM1 ;结果为[(Dr*Cr-Di*Ci)(Dr*Ci+Di*Cr)]

  注意,输出为一个字组。如果需要,可用一条成组指令将结果转换为16位值(与输入格式匹配)。

5.7 无符号数差值的绝对值

  本例计算两个无符号数差值的绝对值。假设是一个无符号字节组数据类型。这里,我们使用无符号饱和模式下的减法指令。指令按无符号饱和方式将无符号操作数相减。仅支持字节组和字组,不支持双字组。

  输入:

MM0: 源操作数
MM1: 源操作数

  输出:

MM0: 无符号数差值的绝对值

MOVQ MM2, MM0 ;制做MMO的备份
PSUBSB MM0, MM1 ;计算差值方法1
PSUBSB MM1, MM2 ;计算差值方法2
POR MM0, MM1 ;将两个差值求或

  如果操作数有符号,本例不执行。有关有符号差值的绝对值请见下一个例子。

5.8 有符号数差值的绝对值

  本例计算两个有符号数差值的绝对值。MMX™指令中没有按无符号饱和方式对有符号 操作数进行减法的操作。这里使用的技巧是,先将两个输入的操作数的对应元素按大小排序,生成一个较大的字组数据和一个较小的字组数据。然后,用较大的值减 去较小的值,就生成了所要求的差值的绝对值。关键是由B=XOR(A,XOR(A,B))和A=XOR(A,0)构成的快速排序技术。然后在成组数据类型 中,使某些元素为XOR(A,B),某些为0,你可以将这一操作数与A进行XOR操作,并在某些地方生成A,某些地方生成B。下例假设一个字组数据类型, 每个元素为一个有符号数值。

  输入:

MM0: 有符号源操作数
MM1: 有符号源操作数

  输出:

MM0: 有符号数的差值的绝对值

MOVQ MM2, MM0 ;制做源操作数1的备份(A)
PCMPGTW MM0, MM1 ;取得源操作数1>源操作数2的标志
MOVQ MM4, MM2 ;制做源操作数A的另一个备份
PXOR MM2, MM1 ;生成交换操作XOR(A,B)的中间值
PAND MM2, MM0 ;生成0s和XOR(A,B)元素的标志
;当A>B为值XOR(A,B),当A<=B为值0
MOVQ MM3, MM2 ;生成交换掩码的备份
PXOR MM4, MM2 ;XOR(A,swap mask)为较小值
PXOR MM1, MM3 ;XOR(B,swap mask)为较大值
PSUBW MM1, MM4 ;差值的绝对值=较大值-较小值

5.9 绝对值

  当X为有符号数时,计算|X|。下例假设操作数为有符号字。

  输入:

MM0: 有符号源操作数

  输出:

MM1: ABS(MM0)

MOVQ MM1, MM0 ;备份X
PSRAW MM0, 15 ;复制符号位(是双字则用31位)
PXOR MM0, MM1 ;如负数则取1的补码
PSUBS MM1, MM0 ;如为负数则加1

  注意 最大的负数(即16位的8000H)所求的绝对值不正确,但该代码对这种情况也是合理的,它使减一的结果为7fffH。

5.10 有符号数截取到任意有符号区域[HIGH,LOW]

  本例说明了如何将一个有符号值截取到有符号区域[HIGH,LOW]。特别是当值小于LOW或大于HIGH时,截取到相应的LOW或HIGH中。本技术按无符号饱和方式进行成组数据加和成组数据减指令,该技术只能用于字节组和字组数据类型。

  下例使用了最大成组数和最小成组数。

  下例显示了对字数据值的操作。为简便起见,使用下列常数(在对字节值操作时,使用相应的常数)。

  • PACKED_MAX=0x7FFF7FFF7FFF7FFF
  • PACKED_MIN=0x8000800080008000
  • PACKED_LOW包含了由LOW值构成的、字组数据类型中的全部4个字。
  • PACKED_HIGH包含了由HIGH值构成的、字组数据类型中的全部4个字。
  • PACKED_USMAX为全1。
  • HIGH_US将HIGH值加到PACKED_MIN中的全部元素上。
  • LOW_US将LOW值加到PACKED_MIN中的全部元素上。

  本例显示了对字数据值的操作。

  输入:

MM0: 有符号源操作数

  输出:

MM0: 按无符号区域[HIGH,LOW]截取的有符号操作数

PADD MM0, PACKED_MIN ;非饱和方式相加并转换为无符号数
PADDUSW MM0, (PACKED_USMAX-HIGH_US)
;截取HIGH
PSUBUSW MM0, (PACKED_USMAX-HIGH_US+L0W_US)
;截取到LOW
PADDW MM0, PACKED_LOW ;取消前两个偏移量

  上述代码先将值转换为无符号数,然后将它们截取到一个无符号区域。最后一条指令将数据转换为有符号数据,并置于有符号区域中。当数据(HIGH-LOW)<0x8000时,将数据转换为无符号数的结果是正确的。

  如果(HIGH-LOW)>=0x8000,算法应按下面所示进行简单修改。

	MM0:	有符号源操作数

  输出:

MM0: 按无符号区域[HIGH,LOW]截取的有符号操作数

PADDSSW MM0, (PACKED_USMAX-HIGH_US) ;截取HIGH
PSUBSSW MM0, (PACKED_USMAX-PACKED_HIGH+PACKED_LOW)
;截取到LOW
PADDW MM0, LOW ;取消前两个偏移量

  如果已知(HIGH-LOW)>=0x8000,本算法则省下一个时钟周 期。为了了解为什么在(HIGH-LOW)<0x8000时,这个由三条指令构成的算法不能工作,注意0xFFFF减任何小于0x8000的数都将 产生一个在数量级上大于负数0x8000的数。当PSUBSSW MM0, (0xFFFF-HIGH+LOW)(三行算法的第二条指令)被执行时,一个负数将被减,造成MM0中的值不减反加,这样就产生了一个不正确的结果。

5.11 无符号数截取到任意无符号区域[HIGH,LOW]

  本例说明了如何将一个无符号数截取到无符号区域[HIGH,LOW]。如果数据小于LOW或者大于HIGH,那么截取到对应的LOW或HIGH中。本技术按无符号饱和方式进行成组数据加和成组数据减指令,该技术只能用于字节组和字组数据类型。

  下例显示了对字数据值的操作。

  输入:

MM0: 无符号源操作数

  输出:

MM0: 按无符号区域[HIGH,LOW]截取的无符号操作数

PADDUSW MM0, 0xFFFF-HIGH ;截取到HIGH
PSUBUSW MM0, (0xFFFF-HIGH+LOW) ;截取到LOW
PADDW MM0, LOW ;取消前两个偏移量


5.12 常数生成

  在MMX™指令集中不存在能够将立即数常数取到MMX™寄存器的指令。下列代码段用于生成MMX™寄存器中的常用常数。当然,也可以将常数作为内存中的局域变量。但是如果要这样做,就要在内存中进行数据的复制,以便可用MOVQ指令读取。

  在MM0中产生0:

PXOR MM0, MM0

  在MM1中产生全1数,每个成组数据类型字段为-1

PCMPEQ MM1, MM1

  为每个字节组[或成组字](或双字组)字段产生常数1

PXOR MM0, MM0
PCMPEQ MM1, MM1
PSUBB MM0, MM1 [PSUBW  MM0, MM1] (PSUBD  MM0, MM1)

  在每个字组(或双字组)中生成有符号常数2n-1

PCMPEO MM1, MM1
PSRLW MM1, 16-n (PSRLD  MM1, 32-n)

  在每个字组(或双字组)字段中生成有符号常数-2n

PCMPEO MM1, MM1
PSLLW MM1, n  (PSLLD  MM1, n)

  由于MMX™指令集不支持字节的移位指令,2n-1和-2n只与字组和双字组相关。

source:http://dev.gameres.com/Program/Other/Fmmx/mmx_c5.htm

2008年3月3日星期一

__attribute__ 问题

测试程序
#include <stdio.h>
struct A{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
};

struct B{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned));

struct C{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned(1)));


struct D{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned(4)));

struct E{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((aligned(8)));

struct F{
        char a;
        int b;
        unsigned short c;
        long d;
        unsigned long long e;
        char f;
}__attribute__((packed));

int main(int argc, char **argv)
{
        printf("A = %d, B = %d, C = %d, D = %d, E = %d, F = %d\n",
                sizeof(struct A), sizeof(struct B), sizeof(struct C), sizeof(struct D), sizeof(struct E), sizeof(struct F));
        return 0;
}
在fedora 7下的测试结果:
A = 28, B = 32, C = 28, D = 28, E = 32, F = 20
A:不使用__attribute__ 默认4字节对齐
B:__attribute__((aligned))
      the compiler automatically sets the alignment for the declared variable or field to the largest alignment which is ever used for any data type on the target machine you are compiling for. Doing this can often make copy operations more efficient, because the compiler can use whatever instructions copy the biggest chunks of memory when performing copies to or from the variables or fields that you have aligned this way.
   最大对齐方式,此例中为16字节对齐,同E
C:__attribute__((aligned(1))) 不支持,除了packed 不能减小对齐字节数,以默认对齐方式对齐
D:__attribute__((aligned(4))) 四字节对齐
E:__attribute__((aligned(8))) 八字节对齐
F:__attribute__((packed))
     the aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well.
     The packed attribute specifies that a variable or structure field should have the smallest possible alignment―one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.

Here is a structure in which the field x is packed, so that it immediately follows a:

          struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
变量以字节对齐,结构体域以位对齐
cygwin下的测试结果:
A = 32, B = 32, C = 32, D = 32, E = 32, F = 20
从测试结果上看默认8字节对齐?或是只支持packed,未知
可参考的文档:
http://developer.apple.com/documentation/DeveloperTools/gcc-3.3/gcc/Variable-Attributes.html
http://www.skynet.org.cn/archiver/?tid-87.html

2008年2月25日星期一

cavs -20080225

修改cavs_decode_frame函数,使其解出一帧数据后返回
static int cavs_decode_frame(AVCodecContext * avctx,void *data, int *data_size,
                             const uint8_t * buf, int buf_size) {
    AVSContext *h = avctx->priv_data;
    MpegEncContext *s = &h->s;
    int input_size;
    const uint8_t *buf_end;
    const uint8_t *buf_ptr;
    AVFrame *picture = data;
    uint32_t stc = -1;

    //add by xugx 20080223
    int ok=0;

    s->avctx = avctx;

    if (buf_size == 0) {
        if(!s->low_delay && h->DPB[0].data[0]) {
            *data_size = sizeof(AVPicture);
            *picture = *(AVFrame *) &h->DPB[0];
        }
        return 0;
    }

    buf_ptr = buf;
    buf_end = buf + buf_size;
    for(;;) {
        //add by xugx 20080223
        if(ok)
        {
            //av_log(avctx,AV_LOG_ERROR,"decode one picture success reutrn %d\n",buf_ptr - buf - s->parse_context.last_index);
            return FFMAX(0, buf_ptr - buf - s->parse_context.last_index);
        }

        buf_ptr = ff_find_start_code(buf_ptr,buf_end, &stc);
        if(stc & 0xFFFFFE00)
            return FFMAX(0, buf_ptr - buf - s->parse_context.last_index);
        input_size = (buf_end - buf_ptr)*8;
        switch(stc) {
        case CAVS_START_CODE:
            init_get_bits(&s->gb, buf_ptr, input_size);
            decode_seq_header(h);
            break;
        case PIC_I_START_CODE:
            if(!h->got_keyframe) {
                if(h->DPB[0].data[0])
                    avctx->release_buffer(avctx, (AVFrame *)&h->DPB[0]);
                if(h->DPB[1].data[0])
                    avctx->release_buffer(avctx, (AVFrame *)&h->DPB[1]);
                h->got_keyframe = 1;
            }
        case PIC_PB_START_CODE:
            *data_size = 0;
            if(!h->got_keyframe)
                break;
            init_get_bits(&s->gb, buf_ptr, input_size);
            h->stc = stc;
            if(decode_pic(h))
                break;
            *data_size = sizeof(AVPicture);
            if(h->pic_type != FF_B_TYPE) {
                if(h->DPB[1].data[0]) {
                    *picture = *(AVFrame *) &h->DPB[1];
                } else {
                    *data_size = 0;
                }
            } else
                *picture = *(AVFrame *) &h->picture;
            //add by xugx 20080223
            ok=1;
            break;
        case EXT_START_CODE:
            //mpeg_decode_extension(avctx,buf_ptr, input_size);
            break;
        case USER_START_CODE:
            //mpeg_decode_user_data(avctx,buf_ptr, input_size);
            break;
        default:
            if (stc >= SLICE_MIN_START_CODE &&
                stc <= SLICE_MAX_START_CODE) {
                init_get_bits(&s->gb, buf_ptr, input_size);
                decode_slice_header(h, &s->gb);
            }
            break;
        }
    }
}

新的main函数,使其解码AVS文件
#define INBUF_SIZE 1024*1024+50000
//#define INBUF_SIZE 1024*512
void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
{
    FILE *f;
    int i;

    f=fopen(filename,"w");
    fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
    for(i=0;i<ysize;i++)
        fwrite(buf + i * wrap,1,xsize,f);
    fclose(f);
}

void yuv_save(unsigned char *buf,int wrap,int xsize,int ysize,FILE *f)
{
    int i;
    for(i=0;i<ysize;i++)
        fwrite(buf+i*wrap,1,xsize,f);
}
 
//void video_decode_example(const char *outfilename, const char *filename)
int main(int argc,char **argv)
{
    char* filename=argv[1];
    char* outfilename=argv[2];


    AVCodec *codec;
    AVCodecContext *c= NULL;
    int frame, size, got_picture, len;
    FILE *f,*fout;
    AVFrame *picture;
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
   //uint8_t inbuf[INBUF_SIZE ], *inbuf_ptr;
    char buf[1024];

    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
   // memset(inbuf , 0, INBUF_SIZE);

    printf("Video decoding\n");

  /* must be called before using avcodec lib */
    avcodec_init();

    /* register all the codecs */
    avcodec_register_all();

    /* find the mpeg1 video decoder */
    codec = avcodec_find_decoder(CODEC_ID_CAVS);
  // codec=&cavs_decoder;
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c= avcodec_alloc_context();
    picture= avcodec_alloc_frame();

    if(codec->capabilities&CODEC_CAP_TRUNCATED)
        c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */

    /* For some codecs, such as msmpeg4 and mpeg4, width and height
       MUST be initialized there because this information is not
       available in the bitstream. */

    /* open it */
    if (avcodec_open(c, codec) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    /* the codec gives us the frame size, in samples */

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
    fout=fopen(outfilename,"wb");
    if(!fout)
    {
        fprintf(stderr,"could not open %s\n",outfilename);
        exit(1);
    }

    frame = 0;
    int i=0;
    int first=1;
    int left=0;
    int sum;
    for(;;) {
        printf("fread %d\n",i++);
        //size = fread(inbuf, 1, INBUF_SIZE, f);
        size = fread(inbuf+left, 1, INBUF_SIZE-left, f);
       printf("size1=%d\n",size);
        size+=left;
        printf("size2=%d\n",size);
        //if (size == 0)
        if(size<=left)
            break;

        /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
           and this is the only method to use them because you cannot
           know the compressed data size before analysing it.

           BUT some other codecs (msmpeg4, mpeg4) are inherently frame
           based, so you must call them with all the data for one
           frame exactly. You must also initialize 'width' and
           'height' before initializing them. */

        /* NOTE2: some codecs allow the raw parameters (frame size,
           sample rate) to be changed at any frame. We handle this, so
           you should also take care of it */

        /* here, we use a stream based decoder (mpeg1video), so we
           feed decoder and see if it could decode a frame */
        inbuf_ptr = inbuf;
        sum=0;
        while (size > 0) {
            len = avcodec_decode_video(c, picture, &got_picture,
                                       inbuf_ptr, size);
            sum+=len;
            printf("len=%d sum=%d\n",len,sum);
            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frame);
                exit(1);
            }
            if (got_picture) {
                printf("saving frame %3d\n", frame);
                fflush(stdout);
                  first=0;
                /* the picture is allocated by the decoder. no need to
                   free it */
                snprintf(buf, sizeof(buf), outfilename, frame);
             //   pgm_save(picture->data[0], picture->linesize[0],
               //          c->width, c->height, buf);
               // printf("linsize0=%d linesize1=%d linesize2=%d\n",picture->linesize[0],picture->linesize[1],picture->linesize[2]);
                //printf("width=%d height=%d\n",c->width,c->height);
                yuv_save(picture->data[0],picture->linesize[0],c->width,c->height,fout);
                yuv_save(picture->data[1],picture->linesize[1],c->width/2,c->height/2,fout);
                yuv_save(picture->data[2],picture->linesize[2],c->width/2,c->height/2,fout);
                frame++;
            }
            /*else*/
            /*{*/
            /*if(!first)*/
            /*{*/
            /*memcpy(inbuf,inbuf_ptr,size);*/
            /*left=size;*/
            /*break;*/
            /*}*/
            /*}*/
       
            size -= len;
            inbuf_ptr += len;
            if(size<60000)
            {
                  memcpy(inbuf,inbuf_ptr,size);
                  left=size;
                  break; 
            }
        }
    }

    //the last buffer content
        inbuf_ptr = inbuf;
        sum=0;
        while (size > 0) {
            len = avcodec_decode_video(c, picture, &got_picture,
                                       inbuf_ptr, size);
            sum+=len;
            printf("len=%d sum=%d\n",len,sum);
            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frame);
                exit(1);
            }
            if (got_picture) {
                printf("saving frame %3d\n", frame);
                fflush(stdout);
                  first=0;
                /* the picture is allocated by the decoder. no need to
                   free it */
                snprintf(buf, sizeof(buf), outfilename, frame);
             //   pgm_save(picture->data[0], picture->linesize[0],
               //          c->width, c->height, buf);
               // printf("linsize0=%d linesize1=%d linesize2=%d\n",picture->linesize[0],picture->linesize[1],picture->linesize[2]);
                //printf("width=%d height=%d\n",c->width,c->height);
                yuv_save(picture->data[0],picture->linesize[0],c->width,c->height,fout);
                yuv_save(picture->data[1],picture->linesize[1],c->width/2,c->height/2,fout);
                yuv_save(picture->data[2],picture->linesize[2],c->width/2,c->height/2,fout);
                frame++;
            }
            size -= len;
            inbuf_ptr += len;
        }
    /* some codecs, such as MPEG, transmit the I and P frame with a
       latency of one frame. You must do the following to have a
    /*       chance to get the last frame of the video */
    /*len = avcodec_decode_video(c, picture, &got_picture,*/
    /*NULL, 0);*/
    /*if (got_picture) {*/
    /*printf("saving last frame %3d\n", frame);*/
    /*fflush(stdout);*/

    /*        *//* the picture is allocated by the decoder. no need to*/
    /*           free it */
    /*snprintf(buf, sizeof(buf), outfilename, frame);*/
    /*pgm_save(picture->data[0], picture->linesize[0],*/
    /*c->width, c->height, buf);*/
    /*frame++;*/
    /*}*/

    fclose(f);
    fclose(fout);

    avcodec_close(c);
    av_free(c);
    av_free(picture);
    printf("\n");
    return 0;
}

2008年2月24日星期日

a script

#!/bin/bash
for i in `ps -a |grep 'tunerapp'|awk '{print $1}'`
do
    kill -9 $i
done
for i in `ps -a |grep 'play_psfdemux'|awk '{print $1}'`
do
    kill -9 $i
done

Fedora配置中文输入法

Feodra 7,8
系统语言英文,ctrl+space 无法调出scim,不能输入中文,

解决方法:

 /etc/sysconfig/i18n中原始内容为
LANG="en_US.UTF-8"
SYSFONT="latarcyrheb-sun16"

在其中加一行
LC_CTYPE="zh_CN.UTF-8"

文件内容变为
LANG="en_US.UTF-8"
 LC_CTYPE="zh_CN.UTF-8"
SYSFONT="latarcyrheb-sun16"

然后重启系统,按ctrl+space就可以启动scim输入中文了。

2008年2月18日星期一

排列生成算法

输出12345五个数字的所有排列情况。

分析:

这五个数字的排列情况是(按由小到大的顺序):

123451235412435124531253412543…..

规律:从右边开始向左扫描,找到前一个比后一个小的位置i,假设该位置的数字用a表示,然后从这个位置的下一个位置开始向右边找,找到比a大的且与a接近的数,设该数用b表示,位置用j表示。交换ab,然后将第i+1到最后一个数按小到的顺序排序,即得到一个新的排列。如1235412435a=3i=3b=4j=5,作如下变化:

找位置,换位置  排序

12354 12453  12435

1NOIP20044题:火星人(martian.pas/c/cpp)

 【问题描述】

     人 类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样 的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回 答。

火星人用一种非常简单的方式来表示数字――掰手指。火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为123……。火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。

一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指――拇指、食指、中指、无名指和小指分别编号为12345,当它们按正常顺序排列时,形成了5位数12345,当你交换无名指和小指的位置时,会形成5位数12354,当你把五个手指的顺序完全颠倒时,会形成54321,在所有能够形成的1205位数中,12345最小,它表示112354第二小,它表示254321最大,它表示120。下表展示了只有3根手指时能够形成的63位数和它们代表的数字:

 三位数

123

132

213

231

312

321

代表的数字

1

2

3

4

5

6

    现 在你有幸成为了第一个和火星人交流的地球人。一个火星人会让你看他的手指,科学家会告诉你要加上去的很小的数。你的任务是,把火星人用手指表示的数与科学 家告诉你的数相加,并根据相加的结果改变火星人手指的排列顺序。输入数据保证这个结果不会超出火星人手指能表示的范围。

 【输入文件】

    输入文件martian.in包括三行,第一行有一个正整数N,表示火星人手指的数目(1 <= N <= 10000)。第二行是一个正整数M,表示要加上去的小整数(1 <= M <= 100)。下一行是1NN个整数的一个排列,用空格隔开,表示火星人手指的排列顺序。

 【输出文件】

    输出文件martian.out只有一行,这一行含有N个整数,表示改变后的火星人手指的排列顺序。每两个相邻的数中间用一个空格分开,不能有多余的空格。

 【样例输入】

5

3

1 2 3 4 5

 【样例输出】

1 2 4 5 3

【数据规模】

对于30%的数据,N<=15

对于60%的数据,N<=50

对于全部的数据,N<=10000

备注:此题故意把问题说得很复杂,很简单,就是一个求排列的问题。


my answer:

#include <stdio.h>

#define size 10010

int N,M;
int num[size];
int main()
{
    freopen("huoxing.txt","r",stdin);
    scanf("%d%d",&N,&M);
    int i;
    for(i=0;i<N;i++)
        scanf("%d",num+i);
    for(i=0;i<M;i++)
    {
        int k=N-1;
        while(num[k-1]>num[k]) k--;
        int k1=k-1;
        int a=num[k1];
        int k2=k;
        int b=num[k];
        for(k++;k<N;k++)
            if ((num[k]<b) &&(num[k]>a))
            {
                b=num[k];
                k2=k;
            }
           num[k1]=b;
           num[k2]=a;
           int tmp;
           int j;
           for(j=N;j>1;j--)
            for(k=k1+2;k<j;k++)
                if(num[k-1]>num[k])
                {
                    tmp=num[k-1];
                    num[k-1]=num[k];
                    num[k]=tmp;
                }
          
    }
    for(i=0;i<N-1;i++)
        printf("%d ",num[i]);
    printf("%d",num[N-1]);
}