2098: 数论之神
描述
题目描述:
终于活成了自己讨厌的样子。
这是她们都还没长大的时候发生的故事。那个时候,栗子米也不需要为了所谓的爱情苦恼。
她们可以在夏日的午后,花大把的时间去研究生活中一些琐碎而有趣的事情,比如数论。
有一天西柚柚问了栗子米一个题,她想知道⌊n1⌋,⌊n2⌋,…,⌊nn⌋\lfloor\frac{n}{1}\rfloor, \lfloor\frac{n}{2}\rfloor, \dots, \lfloor\frac{n}{n}\rfloor⌊1n⌋,⌊2n⌋,…,⌊nn⌋中有多少不同的数,这些不同的数字里面第kkk大的是多少。
输入:
第一行一个整数T(T≤105)T(T\leq 10^5)T(T≤105),表示数据组数。
每组数据第一行两个整数,表示n,k(1≤n≤1018)n,k(1\leq n\leq 10^{18})n,k(1≤n≤1018),保证kkk不会超过不同的数字个数。
输出:
对于每组数据输出,输出两个整数,表示有多少个不同的数字和这里面第kkk大的是多少。
样例输入
3
1 1
5 2
67 8
样例输出
1 1
3 2
15 8
当时这一道题目比赛的时候不会做,等比赛完了的时候,出题人讲了一下思路,补完了题目就算了,也就没有往下面想,回来后发现这个整除是经常用,上一篇博客说了什么是整数除法就是某个数的倍数在这个范围内的个数,并且这个相同的倍数的个数会延伸到哪一个数字,个数(n/i),延伸到哪一个数字(n/(n/i));
并且我们也知道了,一个根号将n/i的数值种类划分为两个层次如果是i<=sqrt(n)的话那么,每一个数字的n/i都是不同的,但是当超过sqrt(n)的时候,每一个数字n/i都是有和他相同的并且是如果这个数字的n/i和上一个n/i不相同的话,和这个n/i相同的n/i会一直到n/(n/i);并且还有就是根号前面的是i相连,后面的是n/i相连;这样时间复杂度是根号的情况下,可以解决相关的问题;
对于这一道题目来说的话就是如果是k<=sqrt(n)的话第二个数值就是a/k,如果是大于sqrt(n)的话,就是sqrt(n)+1对应的n/i减掉k超过sqrt(n)的部分然后是在加上1;
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int Max = 1e3+10;
#define rep(i,s,n) for(ll i=s;i<=n;i++)
#define per(i,n,s) for(ll i=n;i>=s;i--)
int main(){
ll a,k;
int t;
scanf("%d",&t);
while(t--){
scanf("%llu %llu",&a,&k);
ll ans1=(ll)sqrt(a),ans2;
if(ans1*(ans1+1)<=a){
ans1=ans1*2;
}
else {
ans1=2*ans1-1;
}
ll base=(ll)sqrt(a);
if(k<=base) ans2=a/k;
else {
ll n=a/(base+1);
ans2=n-(k-base)+1;
}
printf("%llu %llu\n",ans1,ans2);
}
return 0;
}