Codefoces 955C 题解
作者:互联网
题意简述
多组数据。每次给定l,r(l,r都<=1e18),求l~r中有多少x满足x=ap,其中a和p是两个整数满足a>0,p>1。
数据
输入:
6
1 4
9 9
5 7
12 29
137 591
1 1000000
输出:
2
1
0
3
17
1111
思路
会发现,当p>=3时,使得0<=ap<=1e18的a并不多,p=3大概有1e6,然后后面更少。经计算,总共的个数(去重后)是1003332,就比1e6多一点。考虑暴力存下,排序去重后存着。p>=3的情况只要upperbound−lowerbound即可。记为a1。
那如何处理p=2的情况?
相当于求有多少a满足l<=a2<=r。
我们会发现,如果设S(n)为满足1<=a2<=n的a个数,则我们要求的就是S(r)−S(l−1)。
由数学常识得,S(n)=n。
故我们要求的就是r−l−1。记为a2
然后只要把a1和a2加一起即可。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int Max=1000000ll*1000000ll*1000000ll;//1e18
int Root(int x)
{
return (int)sqrt(x*1.0+0.5);
}
vector<int>tmp;
void Build()
{
for(int i=2;i<=1000000;i++)//枚举底数
{
int s=i*i*i;//至少三次方
while(s<=Max)
{
int rs=Root(s);
if (rs*rs<s) tmp.push_back(s);
//这个就是判s是否是平方数,为了避免和后面考虑p=2的情况重合
if (s>Max/i) break;//如果爆了赶快退出
else s*=i;//没爆继续乘
}
}
sort(tmp.begin(),tmp.end());
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());//排序去重,方便lower_bound和upper_bound
//printf("%d\n",tmp.size());
//=1003332,如果要自己写(即不完全Copy我的),珂以先对一下这个答案
}
int l,r;
void Solve()
{
int a1=upper_bound(tmp.begin(),tmp.end(),r)-lower_bound(tmp.begin(),tmp.end(),l);
int a2=Root(r)-Root(l-1);
printf("%I64d\n",a1+a2);//上面说的a1和a2
}
main()
{
Build();
int T;scanf("%I64d",&T);
while(T--)
{
scanf("%I64d%I64d",&l,&r);
Solve();
}
return 0;
}
标签:tmp,gt,end,Codefoces,题解,955C,3p,int,lt 来源: https://blog.csdn.net/LightningUZ/article/details/89040080