1.递增序列的概念:
一串数的序列,相领两个数之间的差值是固定的,则此数列递增序列,如:
1,2,3,4,5,6,7,8,9,10(差1) 1,3,5,7,9,11(差2)
大家一般都会了解,它的规律是第1个数与倒数第1个数的和,与第二个数与倒数第二个数的和是一样的。这样可以有这样的计算方法:
(Begin + End ) * ( End - Begin ) / 2 就会计算出它的所有数值的总和。
但以上情况是在数值总数量为偶数是有效的,如果是奇数,则需要加入未计算的数值:
( (Begin + End ) * ( End -Begin ) ) / 2 + ( Begin + ( End - Begin ) / 2 + 1 ),这里的第二个括号之中就是未加入的数值。
以上算式为了简单表示,没有加入对数列起点和结果是否在计算范围之中的考虑,如果起点和结束点都在计算范围,长度应+1,如果结束点不在计算范围,和值应-1,如下:
( ( Begin + End - 1 ) * ( End -Begin ) 或
( ( Begin + End ) * ( End - Begin + 1 )
这里一个数列和计算普通方法:
Begin是起点,End是结束点,Space是间隔:
static ULONG SerialNumSum2( ULONG Begin, ULONG End, ULONG Space )
{
ULONG Sum = 0;
INT32 i;
for( i = Begin; i <= End; i += Space )
{
Sum += i;
}
return Sum;
}
这里是使用简算方法实现的方法,并且经过简化只使用一条语句来完成:
#define ALIGNED_END( begin, end, space ) ( end - ( ( end - begin ) % space ) )//计算对齐值
static ULONG SerialNumSum( ULONG Begin, ULONG End, ULONG Space )
{
return ( ( INT32 )( Begin - End ) > 0 ) ? 0 :
( ( ( ( End - Begin ) / Space + 1 ) % 2 ) == 0 ) ?
( Begin + ALIGNED_END( Begin, End, Space ) ) * ( ( ( ( End - Begin ) / Space + 1 ) ) >> 1 ) : //偶数
( Begin + ALIGNED_END( Begin, End, Space ) ) * ( ( ( ( End - Begin ) / Space + 1 ) ) >> 1 ) + Begin + ( ( ( ( ( ( End - Begin ) / Space + 1 ) ) >> 1 ) ) * Space ); //奇数
}
可以用以下方法测试一下,结果都是正确的:
for( int i = 0; i < 100; i ++ )
{
for( int j = 0; j < 1000; j ++ )
{
for( int k = 0; k < 100; k ++ )
{
ULONG TimeQuickSumBegin = GetTickCount();
ULONG Result = SerialNumSum( i, j, k + 1 );
ULONG TimeQuickSumEnd = GetTickCount();
ULONG TimeSumBegin = GetTickCount();
ULONG Result2 = SerialNumSum2( i, j, k + 1);
ULONG TimeSumEnd = GetTickCount();
printf( "Begin %d, End %d, Sapce %d, quick sum is %d time is %d, normal sum is %d time is %d /n",
i,
j,
k + 1,
Result,
TimeQuickSumEnd - TimeQuickSumBegin,
Result2,
TimeSumEnd - TimeSumBegin );
}
}
}