Codeforces 955C Sad powers(数论)

Codeforces 955C Sad powers

题意

q组询问,每次询问给定L,R,求[L,R]区间内有多少个数可以写成ap的形式,其中a>0,p>1,1 ≤ L ≤ R ≤ 1e18。

思路

  • 对于p>2的情况,由于随着指数p的增大,小于1e18的p次幂的数量会急剧减小,总数量的级别在1e6多左右,因此可预处理。L,R不超过1e18,可以直接枚举数字1-1e6,将每个数字不超过1e18的且不是平方数的p次幂推入数组中,排序去重。以便回答询问时可二分求数量。
  • 对于p=2的情况,对上界直接开方,即可知道有多少个平方数。

做法不难,但容易看不清复杂度,以至于想不到做法。建议手写开方,否则误差较大。

代码

#include<bits/stdc++.h>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<"
"
#define sz(x) int(x.size())
#define All(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef priority_queue<int> BQ;
typedef priority_queue<int,vector<int>,greater<int> > SQ;
const int maxn=1e5+10,mod=1e9+7,INF=0x3f3f3f3f;
ll Sqrt(ll x)
{
	ll l=1,r=x,ans=0;
	while (l<=r)
	{
		ll mid=(l+r)>>1;
		ld mul=ld(mid)*mid;
		if (mul<x)
			l=mid+1,ans=mid;
		else if (mul>x)
			r=mid-1;
		else
			return mid;
	}
	return ans;
}
vector<ll> v;
vector<ll>:: iterator End;
void init()
{
	for (ll i=2;i<=1e6;++i)
	{
		ll a=i*i*i;
		ld _a=a;
		while (_a<=1e18)
		{
			ll t=Sqrt(a);
			if (t*t!=a)
				v.pb(a);
			a*=i;
			_a*=i;
		}
	}
	sort(All(v));
	End=unique(All(v));
}
ll count(ll n)
{
	ll p=upper_bound(v.begin(),End,n)-v.begin();
	return Sqrt(n)+p;
}
int main()
{
	init();
	int n;
	cin>>n;
	while (n--)
	{
		ll l,r;
		scanf("%lld%lld",&l,&r);
		printf("%lld
",count(r)-count(l-1));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/orangee/p/9975085.html