FZU Problem 2191 完美的数字

Problem 2191 完美的数字

Accept: 739 Submit: 2634 Time Limit: 1000 mSec Memory Limit : 32768 KB

img Problem Description

Bob是个很喜欢数字的孩子,现在他正在研究一个与数字相关的题目,我们知道一个数字的完美度是 把这个数字分解成三个整数相乘A*A*B(0<A<=B)的方法数,例如数字80可以分解成1*1*80,2*2*20 ,4*4*5,所以80的完美度是3;数字5只有一种分解方法1*1*5,所以完美度是1,假设数字x的完美度为d(x),现在给定a,b(a<=b),请你帮Bob求出

S,S表示的是从a到b的所有数字的流行度之和,即S=d(a)+d(a+1)+…+d(b)。

img Input

输入两个整数a,b(1<=a<=b<=10^15)

img Output

输出一个整数,表示从a到b的所有数字流行度之和。

img Sample Input

1 80

img Sample Output

107

img Source

福州大学第十二届程序设计竞赛

解决方案

这道题有点像脑筋急转弯??? 反正我脑筋转不过来。

分析题意可以知道,因为0<A<=B,而且要求NUM=A*A*B,所以A最大就是三次根号NUM,也就是说,瞬间将数量级下降到10^5,别急,下面的优化更吊,我们假设数据为a,b,那么对于一个确定的A,它所能表示的数最小是A*A*A,最大就是A*A*(b/(A*A)),注意这里的除法是整数的除法,也就是不带小数的,所以这个数是小于等于b的,于是,我们用NUM/(A*A)-A+1就表示从所有小于b且能够拆成A*A*B形式的数字,那么只要让A从1到三次根下b遍历,就可以求出1-b所有数字的完美度之和,注意是1-b而不是a-b,所以我们还需要算出1-(a-1)的完美度之和,算法一样,用之前的结果减去就可以了,这样说很抽象,我们举个具体的例子:

求a=80,b=80的完美度之和,实际上就是求80的完美度

1.三次根下80等于4,所以A可以从1枚举到4

2.A=1时,可以从1*1*1到1*1*80,所以总共80个完美度

3.A=2时,可以从2*2*2到2*2*20,所以总共19个完美度

4.A=3时,可以从3*3*3到3*3*8,总共6个完美度

5.A=4时,可以从4*4*4到4*4*5,总共2个完美度

所以,从1到80中所有的数字的完美度之和为107

然后要计算从1到79所有的完美度之和,A仍然是从1枚举到4

1.A=1时,可以从1*1*1到1*1*79,总共79个完美度

2.A=2时,可以从2*2*2到2*2*19,总共,18个完美度

3.A=3时,可以从3*3*3到3*3*8,总共6个完美度

4.A=4时,可以从4*4*4到4*4*4,总共1个完美度

所以从1到79总共104个完美度

107-104=3,所以,80的完美度是3
原文:https://blog.csdn.net/wr132/article/details/45461703

思想想起来比较难,倒是代码却比较简单。

#include<iostream>
#include<cmath>
using namespace std;
#define ll long long
int main() {
	ll a, b, ans;
	ll up, down;
	ll i;
	while (cin >> a >> b) {
		ans = 0;
		--a;//减去1 - (a-1)的完美度
		up = pow(b, 0.333333333333);
		down = pow(a, 0.333333333333);
		for (i = 1; i <= up; i++) {
			ans += b / (i*i) - i + 1;
		}
		for (i = 1; i <= down; i++) {
			ans -= a / (i*i) - i + 1;
		}
		cout << ans << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值