前言
模拟赛的一道 T 1 T1 T1 ,被完虐,记录一下。
题意
给定 t t t 组询问的 n n n ,求满足 x y + 1 xy+1 xy+1 ∣ | ∣ x 2 + y 2 x^2+y^2 x2+y2 的有序正整数对 $(x,y) $的个数,其中 1 ≤ x ≤ y ≤ n 1\le x\le y\le n 1≤x≤y≤n。
t ≤ 1 0 5 t\le 10^5 t≤105 , 1 ≤ n ≤ 1 0 18 1\le n\le 10^{18} 1≤n≤1018
样例
输入:
10
10
100
1000
10000
100000
114514
1919810
20190104
123123123123
10000001000000
输出:
2
5
14
31
65
67
158
326
5226
22091
解题方法
传说中的题目长度与题目难度成反比例…
容易想到本题不能在线处理,因为很难做到 O ( log n ) O(\log n) O(logn) 的在线处理,所以考虑预处理解法。从很友好的样例来看,在 n n n 极大的情况下,答案依然较小,很好想到列出所有可能的方案的 y y y ,排序后每次询问就可以二分查找。期望回答询问的复杂度是 O ( t log n ) O(t\log n) O(tlogn) ,比较吻合的数据范围让我们坚信这一定是正解,只要解决列举的复杂度问题即可。
短暂尝试后会发现没有什么很显然的性质,而 y y y 注定无法枚举,所以尝试枚举 x x x ,如果能快速求出所有的 y y y 就好了(有一种思路是枚举 x 2 + y 2 = k ( x y + 1 ) x^2+y^2=k(xy+1) x2+y2=k(xy+1) 的 k k k ,但事实上依然是 1 0 12 10^{12} 1012 数量级的,且无法直接算出)。
变形式子,得 x 2 + y 2 − k x y − k = 0 x^2+y^2-kxy-k=0 x2+y2−kxy−k=0 ,对 y y y 应用主元法,得 y 2 − k x ⋅ y + x 2 − k = 0 y^2-kx\cdot y+x^2-k=0 y2−kx⋅y+x2−k=0 ,这是一个含参的一元二次方程,由于判别式含根号,不利于运算,想到韦达定理,得 y 1 + y 2 = k x y_1+y_2=kx y1+y2=kx , y 1 y 2 = x 2 − k y_1y_2=x^2-k y1y2=x2−k ,其中令 y 1 ≥ y 2 y_1\ge y_2 y1≥y2 。
下面补充判别式的特殊情况
Δ = k 2 x 2 − 4 x 2 + 4 k = ( k 2 − 4 ) x 2 + 4 k \Delta=k^2x^2-4x^2+4k=(k^2-4)x^2+4k Δ=k2x2−4x2+4k=(k2−4)x2+4k
因为 x , k x,k x,k 均为正整数,所以只有 k = 1 k=1 k=1 时判别式才可能是负数,而 x 2 + y 2 = x y + 1 x^2+y^2=xy+1 x2+y2=xy+1 意味着 ( x − y ) 2 = 1 − x y ≥ 0 (x-y)^2=1-xy\ge 0 (x−y)2=1−xy≥0
仅 x = 1 , y = 1 x=1,y=1 x=1,y=1 可满足,特判一下。
以下均讨论 k ≥ 2 k\ge 2 k≥2 时的情况。
假设对于一个固定的 x x x ,我们已知一组解 ( x , y 1 ) (x,y_1) (x,y1) ,于是有 y 2 = k x − y 1 y_2=kx-y_1 y2=kx−y1 也是原方程的一个解。
由 y 1 y 2 = x 2 − k < x 2 y_1y_2=x^2-k<x^2 y1y2=x2−k<x2 和 y 1 ≥ x y_1\ge x y1≥x ,易知 y 2 < x y_2<x y2<x ,于是 ( y 2 , x ) (y_2,x) (y2,x) 也成了一组解,类似于 g c d gcd gcd ,可以逆推处理。
其中的每组解一定单调递减( y 1 ≥ x > y 2 y_1\ge x>y_2 y1≥x>y2),又有正整数的限制,所以一定有一组边界,使其无法再逆推。什么意思呢,就是说有一组解找不到符合题意的 y 2 y_2 y2 了,即 y 2 ≤ 0 y_2\le 0 y2≤0 。假设 y 2 y_2 y2 是负数,带回原方程,有 − k x y − k ≥ 0 -kxy-k\ge 0 −kxy−k≥0 ,所以 y 2 − k x y + x 2 − k > 0 y^2-kxy+x^2-k>0 y2−kxy+x2−k>0 ,不符合。因此 y 2 = 0 y_2=0 y2=0 ,即 k x − y 1 = 0 kx-y_1=0 kx−y1=0 。
把 y = k x y=kx y=kx 带回原方程,可以得到 k = x 2 k=x^2 k=x2 ,所以我们就可以通过 x x x 得到 k , y 1 k,y_1 k,y1 了,然后,既然可以逆推,也一定可以递推,即 ( x , y [ = k x = x 3 ] ) → ( x 3 , x 5 − x ) → ⋯ (x,y[=kx=x^3])\rightarrow(x^3,x^5-x)\rightarrow \cdots (x,y[=kx=x3])→(x3,x5−x)→⋯ ,然后本题就终于做完了。
复杂度是正确的,因为 x x x 只需枚举到 1 0 6 10^6 106 ,而且显然指数级别的增长不会很大,就算全是 2 2 2 ,也不会超时 ( 60 ∗ 1 0 6 < 1 0 8 ) (60*10^6<10^8) (60∗106<108) 。
写在最后
这思路有点离谱,虽然没用到过任何高级算法、数论知识,但是真的难。其实规律能接受,但证明过程真的复杂。
这题据说可以打表找规律,但我没找到,我太蒻了