如果L] = A mod b,则一对正整数(A, b)称为特殊整数。在这里,L]是A与b的整数除法的结果,而A mod其余数。给定两个整数z和y。求出满足1≤a≤x和1≤b≤y的特殊对(a, b)的个数。输入第一行包含一个整数t (1 < t < 100)——测试用例的数量。每个测试用例描述的唯一一行包含两个整数z, y(1≤z, y≤10°)。输出对于每个测试用例,将答案打印在一行上。
Example
input
Copy
9 3 4 2 100 4 3 50 3 12 4 69 420 12345 6789 123456 789 12345678 9
output
Copy
1 0 2 3 5 141 53384 160909 36
请注意在第一个测试用例中,唯一的特殊对是(3,2)。在第二个测试用例中,没有特殊的对。在第三个测试用例中,有两个特殊的对:(3,2)和(4,3)。
题解:
a/b = a%b
通过枚举一些数我们可以发现
k(b + 1)/b = k*(b + 1)%b
并且k < b
其次算一下分界值
i - 1 = a/(i + 1)
i之前的都可以拿i-1个,
整除分块的模板
ans = 0;
for(int l = 1, r; l <= n; l = r + 1)
{
r = n / (n / l);
ans += n / l * (r - l + 1);
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
using namespace std;
int mod = 1e9 + 7;
typedef long long ll;
void solve()
{
ll x,y;
cin >> x >> y;
ll ans = 0;
ll ma = 1e9;
for(ll i = 1;i <= y;i++)
{
if((i - 1)*(i + 1) <= x)
ans += i - 1;
else
{
ma = i;
break;
}
}
for(ll i = ma,r;i <= y;i = r + 1)
{
ll t = x/(i + 1);
if(t == 0)
break;//t = 0,说明块已经分完,结束了
r = min(x/t - 1,y);//和普通整除分块不同的是t = x/(i + 1) 而不是i,所以考虑到精度要- 1,可能会出现x/t - 1大于y的情况,所以取min
ans += (r - i + 1)*t;
}
cout << ans <<"\n";
}
//3 6 6
//111111000
//110111001
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}