Problem 2191 完美的数字
Accept: 739 Submit: 2634 Time Limit: 1000 mSec Memory Limit : 32768 KB
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)。
Input
输入两个整数a,b(1<=a<=b<=10^15)
Output
输出一个整数,表示从a到b的所有数字流行度之和。
Sample Input
1 80
Sample Output
107
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;
}
}