2021牛客寒假算法基础集训营2 D.牛牛与整除分块(规律)

D.牛牛与整除分块
题目链接:https://ac.nowcoder.com/acm/contest/9982/D

题目描述:

整除分块,又称数论分块。是数论算法中的重要技巧,你可以在各种需要枚举因子的连续求和类问题中见到它的身影。如杜教筛,莫比乌斯反演化简后的整除分段求和等。
整除分块基于这样一个数学现象:对于任意正整数N,集合在这里插入图片描述的大小总是严格小于2 √N,例如当N=10时S={10,5,3,2,1},这就使得对于在这里插入图片描述
类型的求和类问题,只要快速枚举S集合,就能在√N 级别的复杂度内解决问题。

⌊ ⌋符号是向下取整符,⌊x⌋表示不大于x的最大正整数。

牛牛在学习整除分块这一算法后提出了一个新的问题,对于给定正整数N,x,令在这里插入图片描述在这里插入图片描述在S中是第几大呢(去重降序排序后第几个)?

输入描述:

第一行输入一个正整数T(1 ≤ T ≤ 10^6 ),表示测试案例的数目,对于每组案例。
一行两个正整数N,x(1 ≤ x ≤ N ≤ 10^9 )。

输出描述:

对于每个案例,输出一个正整数,即在这里插入图片描述在集合S中降序排第几大。

示例1:

输入
2
25 9
1000000000 1000000000
输出
8
63244
说明
当n=25时候,S={25,12,8,6,5,4,3,2,1}⌊ 25/9⌋=2,2在S集合中是降序排列的第8个,所以输出8。

解题思路:

找规律
当k小的时候答案为k,通过找规律可以发现划分的界限大概为√N附近,以25为例,25/i的值为25,12,8,6,5,4,3,2,1。将最大数与最小数两两配对,发现它们的乘积最接近25。因此当x≤√N时,每个x对应不同的答案。否则看N/√N与⌊ N/x⌋之间差多少,根据对称性即可得出结果。

代码如下:

#include <iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
typedef long long ll;
int main()
{
    
    
	int t;
	scanf("%d", &t);
	while(t--)
	{
    
    
		ll x,n;
		scanf("%lld %lld", &n,&x);
		ll cnt = floor(sqrt(1.0*n));
		ll k = n/(cnt+1);
		if(x <= cnt)
			printf("%lld\n",x);
		else
			printf("%lld\n",cnt+(k-n/x)+1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45894701/article/details/113674847