#2021牛客暑假多校3_E.Math_数论打表

E.Math

题面:

#2021牛客暑假多校3_E.Math_数论打表

题目大意:

给定 n n n的情况下,问你在 1 ≤ x ≤ y ≤ n 1≤x≤y≤n 1≤x≤y≤n的范围内,能找到多少组数对 ( x , y ) (x,y) (x,y),使得 x 2 + y 2 x^2+y^2 x2+y2除以 x ∗ y + 1 x*y+1 x∗y+1是一个整数。
输出数量。

题目思路:

先打个表找规律。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int main() {
    int i=10000;
    ll cnt = 0;
    cout << i << ":" << endl;
    for (int m = 1; m <= i; m++)
        for (int n = m; n <= i; n++) {
            if ((m * m + n * n) % (m * n + 1) == 0) {
                cnt++;
                cout << cnt << ":" << m << " " << n << endl;
            }
        }
    cout << cnt << endl;
    cout << endl;

}

关于这组数
是某年的IMO题,关键点是韦达跳跃。

打表结果如下:
#2021牛客暑假多校3_E.Math_数论打表
x与y为三次方倍关系的很常见,再把不正常的筛选出来看看:
8 30
30 112
27 240
112 418
64 1020
418 1560
240 2133
125 3120
1560 5822
216 7770
343 16800
2133 18957

里面出现了一些首尾相关的部分:
8->30->112->418->1560->5822
27->240->2133->18957
64->1020->16256
125->3120

发现:

  1. 都是 w 3 w^3 w3开头
  2. a i + 1 = a i ∗ ( w 2 ) − a i − 1 a_i+_1=a_i*(w^2)-a_i-_1 ai​+1​=ai​∗(w2)−ai​−1​

30 = 8 ∗ 2 2 − 2 30=8*2^2-2 30=8∗22−2
112 = 30 ∗ 2 2 − 8 112=30*2^2-8 112=30∗22−8

由这个规律开始打表做。

代码:

#include <bits/stdc++.h>

#define ll unsigned long long
using namespace std;
vector<ll> st;

int main() {
    st.push_back(1);
    for (ll i = 2; i <= (1e6); i++) {
        ll now = i * i * i, pre = i;
        while (now <= (1e18)) {
            st.push_back(now);
            if (now > (1e18 + i) / (i * i)) break;
            //小 心 爆 炸
            ll tp = i * i * now - pre;
            if (tp > 1e18)break;
            //小 心 爆 炸
            pre = now;
            now = tp;
        }
    }
    sort(st.begin(), st.end());
    //for(int i=0;i<=10;i++)cout<<st[i]<<'\n';
    ll t;
    cin >> t;
    while (t--) {
        ll n;
        cin >> n;
        ll p = lower_bound(st.begin(), st.end(), n + 1) - st.begin();
        cout << p << '\n';
    }
}
上一篇:175-C++重要知识点6


下一篇:LeetCode-112-路径总和