Lightoj 1234 分步打表法 求调和级数

本文介绍了一种针对大规模数据求和的优化算法,通过分步打表法将计算复杂度从O(n)降低到接近O(1),适用于n小于等于1亿的场景。算法首先预计算每100的倍数的累加和,存储于数组中,对于任意输入值,可通过查找数组和最多100次额外计算获得结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:对一个正整数n(n <= 10^8),求Σ(1/k) (1<=k<=n)。

题解:分步打表

1.1e8太大了数组开不下,所以想到缩小100倍,开一个1e6的数组。即计算每个x(x%100=0)对应的求和值。

2.然后对于一个输入的x值可由已计算的数加上不超过100次的计算得到。

#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
#define maxn 100000005
using namespace std ;
double sum[1000005] ;
void init() //分步打表法第1步 
{
	int i ;
	double ans = 0 ;
	sum[0] = 0 ;
	for(i = 1 ; i <= maxn - 5 ; i ++)
	{
		ans += 1 / double(i) ;
		if(i % 100 == 0) //将打表大小缩小100倍 
		   sum[i / 100] = ans ;
	}
}
int main()
{
	int t , n , x ;
	int i , j , k ;
	int begin , end ;
	int cnt = 0 ;
	double ans ;
	init() ;
	scanf("%d" , &t) ;
	while(t --)
	{
		scanf("%d" , &n) ;
	    begin = n / 100 * 100 + 1 ;
	    end = n / 100 * 100 + n % 100 ;
	    ans = sum[n / 100] ;
	    //分步打表法第2步 
		for(i = begin ; i <= end ; i ++) //1个数最多计算100次 
		    ans += 1 / double(i) ;
	    printf("Case %d: %.10lf\n" , ++cnt , ans) ;
	}
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值