2017西安交大ACM小学期数论 [水题]

水题

发布时间: 2017年6月25日 14:06   最后更新: 2017年7月3日 09:27   时间限制: 1000ms   内存限制: 128M

平均因数个数的统计对于估算数论题目复杂度具有非常重要的意义。小A同学听了今天的课后,于是想要自己写一个程序,求出1到n的平均因数个数。小A当然会啦!但是他想考考你。

多组输入数据(不超过1000组)。
每组一个正整数 n(n109) ,如题目所述。

输出1到n中的平均因数个数,精确到9位小数。

4
20170703
2.000000000
16.974173533
平均因数的个数计数,很简单嘛

1~n的因数的个数总数为


而由公式我们可以将上面的式子变换成为


也就是


对这个东西进行求和也是比较简单的,注意不能暴力求和,因为时间复杂度太高了

我们考虑一个例子,当n为8的时候

[8/1]+[8/2]+[8/3]+[8/4]+[8/5]+[8/6]+[8/7]+[8/8]

=8+4+2+2+1+1+1+1

我们可以发现光1就出现了4次,2出现了2次,剩下的都出现了1次。这也就意味着,我们可以进行统计

我们统计除数为d的出现次数,那么d出现的次数可以表示为k = [n/d]-[n/(d+1)]

那么,它对答案的贡献就是d*k,下一次d就变成了d+1

当我们第一次发现d出现1次的时候,这代表着下面所有的d也都只会出现一次了,我们求出这时候的分母f

将f循环到1,并直接暴力算出结果。


代码:

#include <cstdio>
#include <map> 
#include <iostream>
using namespace std;
typedef long long LL;
int main(){
	LL n;
	while(scanf("%lld",&n) != -1){
		LL res = 0;
		LL d = 1;
		while(d <= n){
			//++cnt;
			LL nex = d+1;
			LL k = n/d - n/nex; 
			if(k == 1){
				for(int i = n/d;i >= 1;i--){
					res += n / i;
				}
				break;
			}
			res += d*k;
			d = nex;
		}
		printf("%.9lf\n",double(res)/n);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值