如下。
再说一句,这里需要注意的是最后的那个把k的范围缩短为
x
\sqrt{x}
x之前的那个算式,
∑
k
=
1
y
−
1
\sum_{k=1}^{y-1}
∑k=1y−1
m
a
x
(
m
i
n
(
x
/
k
−
1
,
y
)
−
k
,
0
)
max(min(x/k-1,y)-k,0)
max(min(x/k−1,y)−k,0), 这里如果思考把
m
a
x
(
m
i
n
(
x
/
k
−
1
,
y
)
−
k
,
0
)
max(min(x/k-1,y)-k,0)
max(min(x/k−1,y)−k,0)换成一个简单的式子以利用整除分块会引来更大的麻烦,而且不可取。所以,缩小范围为
n
\sqrt{n}
n是一种不错的技巧。
#include <bits/stdc++.h>
#define int long long
#define ll long long
using namespace std;
template <class cl>
void read(cl &x)
{
x = 0;
int f = 0;
char ch;
ch = getchar();
while (!isdigit(ch))
{
f = f | (ch == '-'), ch = getchar();
}
while (isdigit(ch))
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x = f ? -x : x;
return;
}
template <class cl>
void put(cl x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
put(x / 10);
putchar(x % 10 + '0');
return;
}
/*inline void to()
{
// 注意这里的int是#define int long long int 过不去。
int x,y;
read(x);
read(y);
int tt=sqrt((long double)x);//写成long double 开long long 保险。
tt=min(y-1,tt);
int ans=0;
// int zz;
for(int k=1;k<=tt;k++)
{
ans=ans+max(min(x/k-1,y)-k,(ll)0); //max(int,int)或者max(long long,long long)
//max(long long ,int )错误。
}
put(ans);
puts("");
return ;
}*/
inline void to()//更好的写法。
{
int x,y;
read(x);
read(y);
int ans=0;
for(int k=1;k<=x/k&&k<=y-1;k++)
{
ans+=max(min(x/k-1,y)-k,(ll)0);
}
put(ans);
puts("");
return ;
}
signed main()
{
int t;
read(t);
while(t--)
{
to();
}
return 0;
}
有关缩小范围到 n \sqrt{n} n的一些例子。(待续)。