自己偶然看到的一个题目对它进行了进一步的思考。
题目大意
求第一象限中位于xy=k下面的点对的个数是多少?
个人YY
我们可以先做一遍暴力(手玩也可以),比如说k=4时,
我们可以列出以下的满足题意的点对
(1,4) (1,2) (1,3) (1,4)
(2,1) (2,2)
(3,1)
(4,1)
进一步思考,题意可转化为求
∑i=1kki
暴力的话要k^2,但是显然我们可以不用枚举那么多,只要枚举根号k次就好了。
我们发现求k/i时,会出现一段的连续答案,于是我们可以采用分块!
分块
先枚举i从1到根号k
假设当前做到的块开头是j,结尾时j’
那么我们可以在当前的块上统计答案,然后再跳下一段块
我们要使
kj>=kj′
移项可得 j′>=kkj
然后我们就可以愉快地分块计算了
时间复杂度可简化为O(根号k)
伪代码
#include<cstdio>
typedef long long LL;
const LL maxn=998244353;
LL calc(LL n)
{
LL x=0,y,sum=0;
while (x<=n)
{
y=n/(n/x);
sum=(sum+(y-x+1)*(n/x)%modn)%modn;
x=y+1;
}
return sum;
}
LL n;
int main()
{
scanf("%lld\n",&n);
printf("%lld\n",calc(n));
}