Sol
(
−
1
)
a
=
1
−
2
(
a
m
o
d
2
)
=
1
−
2
a
+
4
⌊
a
2
⌋
(-1)^a=1-2(a~mod~2)=1-2a+4\lfloor\frac{a}{2}\rfloor
(−1)a=1−2(a mod 2)=1−2a+4⌊2a⌋
那么原式变成
n
−
2
∑
i
=
1
n
⌊
d
r
⌋
+
4
∑
i
=
1
n
⌊
d
r
2
⌋
n-2\sum_{i=1}^{n}\lfloor d\sqrt{r}\rfloor+4\sum_{i=1}^{n}\lfloor \frac{d\sqrt{r}}{2}\rfloor
n−2∑i=1n⌊dr⌋+4∑i=1n⌊2dr⌋
考虑计算这样一个东西
∑
i
=
1
n
⌊
a
∗
r
+
b
c
i
⌋
\sum_{i=1}^{n}\lfloor\frac{a*\sqrt{r}+b}{c}i\rfloor
i=1∑n⌊ca∗r+bi⌋
如果
r
\sqrt{r}
r 是一个整数,直接
Θ
(
1
)
\Theta(1)
Θ(1) 计算
否则
设
k
=
a
∗
r
+
b
c
k=\frac{a*\sqrt{r}+b}{c}
k=ca∗r+b
如果 k ≥ 1 k\ge 1 k≥1 那么可以把 k k k 的整数部分的值算出来,变成 0 < k < 1 0<k<1 0<k<1
如果 0 < k < 1 0<k<1 0<k<1,即就是计算 y = k x y=kx y=kx 与 x = n x=n x=n 所围成三角形的整点个数
根据类欧几里得那一套理论,我们用矩形的减去左上角的三角形的
矩形的就是
n
⌊
n
k
⌋
n\lfloor nk\rfloor
n⌊nk⌋
左上角的三角形的把它关于
y
=
x
y=x
y=x 对称,变成求
y
=
x
k
y=\frac{x}{k}
y=kx 与
x
=
⌊
n
k
⌋
x=\lfloor nk\rfloor
x=⌊nk⌋ 所围成三角形的整点个数
这样可以递归下去, n n n 的规模减小得很快,最后计算 n ≤ 1 n\le 1 n≤1 的答案即可
为了防止精度误差,可以把
k
k
k 表示成
a
∗
r
+
b
c
\frac{a*\sqrt{r}+b}{c}
ca∗r+b 将
a
,
b
,
c
a,b,c
a,b,c 存下来
每次弄走
g
c
d
gcd
gcd 就可以了
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, ans, r, test;
double sq;
inline ll Gcd(ll a, ll b) {
if (!a || !b) return a | b;
return !b ? a : Gcd(b, a % b);
}
inline ll Solve(ll a, ll b, ll c, ll len) {
if (!len) return 0;
register ll sk, nxt, ret, d;
d = Gcd(Gcd(a, b), c), a /= d, b /= d, c /= d;
if (len == 1) return (ll)(1.0 * (sq * a + b) / c);
register double k = 1.0 * (sq * a + b) / c;
sk = (ll)k, k -= sk, nxt = (ll)(k * len), b -= c * sk;
ret = len * nxt + sk * (len + 1) * len / 2;
return ret - Solve(a * c, -b * c, a * a * r - b * b, nxt);
}
int main() {
scanf("%d", &test);
while (test--) {
scanf("%d%d", &n, &r), sq = sqrt(r), ans = sq;
if (ans * ans == r) printf("%d\n", (ans & 1) ? ((n & 1) ? -1 : 0) : n);
else printf("%lld\n", n - 2 * Solve(1, 0, 1, n) + 4 * Solve(1, 0, 2, n));
}
return 0;
}