您的位置:首页 > 其它

FZU 2191 完美的数字

2015-05-03 21:18 337 查看
Problem 2191 完美的数字

Accept: 50    Submit: 146

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

#include <iostream>
#include <cmath>
#include <stdio.h>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <iomanip>
#include <algorithm>
#include <memory.h>
using namespace std;
long long Count;
int main()
{
long long i,j;
long long mul;
long long a,b;
long long up1,up2;
long long s,e;
while(cin>>a>>b)
{
Count=0;
up1=pow(a-1,0.33333333333333);
up2=pow(b,0.33333333333333);
for(i=1;i<=up2;i++)
{
s=i;
e=b/(i*i);
// cout<<s<<' '<<e<<endl;
Count+=e-s+1;
}
for(i=1;i<=up1;i++)
{
s=i;
e=(a-1)/(i*i);
Count-=e-s+1;
}
cout<<Count<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  FZU 2191 完美的数字