题目:链接
咕咕最近在学习初等数论,并且对下取整函数产生了极大的兴趣。下取整函数是指一个函数,自变量为 一个实数,因变量为一个整数,这个整数恰好是小于或等于自变量的最大的整数,通常记做 ⌊x⌋。例如, ⌊2.5⌋ = 2,⌊2⌋ = 2,⌊−2.5⌋ = −3。
咕咕发现,给定一个 a,并不是所有的自然数 n 都存在一个正整数 i 使得 ⌊n/i⌋ = a。那么,如果给定 l,r,咕咕好奇在区间 [l,r] 中有多少个正整数能使这个等式有正整数解 i 呢?
那么,聪明的你,你能告诉咕咕吗?
输入
第一行有一个整数 T(1 ≤ T ≤ 106),表示数据组数。接下来有 T 行,每行有三个数 a,l,r(1 ≤ a ≤ 1018,1 ≤ l ≤ r ≤ 1018),表示一组询问。
输出
输出 T 行,对每组询问,输出一个整数表示答案。
样例输入 Copy
4 5 7 10 7 39 42 1000 1000 1000 27 100 1000
样例输出 Copy
1 2 1 617
提示
数据范围
当 n = 39,a = 7 时,能找到 i = 5 使得 ⌊39 /5 ⌋ = 7。
题解:
由题意可知,满足条件的n分布在如下区间:
1倍区间:[a,a+1) 个数:1
2倍区间:[2a,2(a+1)) 个数:2
3倍区间:[3a,3(a+1)) 个数:3
……
a倍区间:[a*a,a(a+1)) 个数:a
a+1倍区间开始每个区间都有重叠部分,可以推出a*a+1之后的数均满足题意
对于[l,r]区间内的数,先计算出[1,r]内符合题意个数,再计算出[1,l-1]内符合题意个数,取差即为解。!!!!
!!!!注意
输出时必须使用printf输出格式,否则会超时。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll T,l,r,a;
ll solve(ll n)
{
if(n<1) return 0;
ll ans=0;
ll k=n/a;
if(k>a)
{
ans+=((a+1)*a/2);
ans+=n-(a+1)*a+1;
// cout<<ans<<endl;
// if(n>=k*(a+1))
// {
// ans+=(a+1);
// }
// else if(n>=k*a+k-a-1)
// {
// ans+=(n-k*a-k+1+a);
// }
// cout<<ans<<endl;
}
else
{
ans+=(k*(k-1)/2);
if(n>=k*(a+1))
{
ans+=k;
}
else
{
ans+=(n-k*a+1);
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--)
{
cin>>a>>l>>r;
ll ans;
ans=solve(r)-solve(l-1);
printf("%lld\n",ans);
}
return 0;
}
反思:比赛时推出规律,但是直接计算[l,r]区间情况太多,也是没有考虑完全的原因,一直答案错误;
通过计算[1,r],[1,l-1]区间,减少了讨论情况的次数。