AtCoder ABC322G 数学 + 暴力

题意

传送门 AtCoder ABC322G Two Kinds of Base

题解

根据 1 ≤ X 1\leq X 1≤X,以及 f ( S , a ) f(S,a) f(S,a) 关于 a a a 的递增性,可以得到 b < a b<a b<a。此时 S i < min ⁡ ( 10 , a , b ) S_i<\min(10,a,b) Si<min(10,a,b) 简化为 S i < m i n ( 10 , b ) S_i<min(10,b) Si<min(10,b)。根据 S 1 ≠ 0 S_1\neq 0 S1=0,可以观察到 k k k 规模为 O ( log ⁡ X ) O(\log X) O(logX)。

先考虑 k k k 较小的情况。当 k = 1 k = 1 k=1,由于 0 < X 0<X 0<X 故无解;当 k = 2 k = 2 k=2,则 ( a − b ) S 1 = X (a-b)S_1=X (a−b)S1=X,枚举 S 1 , S 2 S_1, S_2 S1,S2,则 a a a 的最小值为 max ⁡ ( S 1 , S 2 ) + 1 + X / S 1 \max(S_1, S_2) + 1 + X/S_1 max(S1,S2)+1+X/S1,最后根据 a ≤ N a\leq N a≤N 统计答案即可。

当 k ≥ 3 k\geq 3 k≥3,则满足 a 2 − b 2 ≤ X a^2-b^2\leq X a2−b2≤X,令 d = a − b d = a - b d=a−b,则有 2 b + d ≤ X / d 2b+d\leq X/d 2b+d≤X/d,可以推出满足条件的 ( a , b ) (a,b) (a,b) 数目为 O ( X log ⁡ X ) O(X\log X) O(XlogX)。那么枚举满足 d ∣ X d|X d∣X 的 d d d,再根据上界枚举 b b b 即可得到所有的 ( a , b ) (a,b) (a,b) 二元组。问题转化为 a , b a,b a,b 固定后满足条件的 S S S 数量,由于 S i S_i Si 上界为 b − 1 b-1 b−1,同时根据等比数列求和公式,可以得到 a k − b k > ( b − 1 ) ∑ i = 0 k − 1 ( a i − b i ) a^k-b^k>(b-1)\sum_{i = 0}^{k-1}(a^i-b^i) ak−bk>(b−1)∑i=0k−1(ai−bi),可以推出满足条件的 S k , S k − 1 , ⋯   , S 2 S_k,S_{k-1},\cdots,S_2 Sk,Sk−1,⋯,S2 至多有一种可能,按照 k k k 从大到小依次减去 a k − b k a^k-b^k ak−bk 的贡献,判断 f ( S , a ) − f ( S , b ) = X f(S,a)-f(S,b)=X f(S,a)−f(S,b)=X 是否成立即可,若成立,对答案贡献为 min ⁡ ( 10 , b ) \min(10,b) min(10,b)。总时间复杂度 O ( X log ⁡ 2 X ) O(X\log^2 X) O(Xlog2X)。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
constexpr int MOD = 998244353;
using ll = long long;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, x;
    cin >> n >> x;
    ll res = 0;
    for (int s1 = 1; s1 < 10; ++s1) {
        if (x % s1 > 0) {
            continue;
        }
        for (int s2 = 0; s2 < 10; ++s2) {
            int d = x / s1;
            int mn = max(s1, s2) + 1 + d;
            (res += max(0, n - mn + 1)) %= MOD;
        }
    }
    for (int d = 1; d <= x; ++d) {
        if (x % d > 0) {
            continue;
        }
        for (int b = 1, a = b + d; a <= n && (ll)a * a - (ll)b * b <= x; ++b, ++a) {
            vector<int> as, bs;
            ll aa = 1, bb = 1;
            while (aa - bb <= x) {
                as.push_back(aa);
                bs.push_back(bb);
                aa *= a, bb *= b;
            }
            int rem = x;
            for (int i = (int)bs.size() - 1; i > 0; --i) {
                int t = rem / (as[i] - bs[i]);
                if (t >= min(10, b)) {
                    break;
                }
                rem -= t * (as[i] - bs[i]);
            }
            if (rem == 0) {
                res += min(10, b);
            }
        }
    }
    res %= MOD;
    cout << res << '\n';

    return 0;
}
相关推荐
朝朝辞暮i8 分钟前
C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针
开发语言·c++·算法·ros2
垆边人似月.21 分钟前
华为题:污染水域
算法
All for pursuit.41 分钟前
【回溯-6】79.单词搜索
数据结构·c++·算法·leetcode
ZhangJun9544 分钟前
Mobike 共享单车分析项目
人工智能·python·算法·kmeans·聚类·knn
Navigator_Z1 小时前
LeetCode //C - 1281. Subtract the Product and Sum of Digits of an Integer
c语言·算法·leetcode
薛定e的猫咪1 小时前
(AISTATS 2023)BaCaDI 逐章阅读
人工智能·深度学习·算法·机器学习
Benny_Tang1 小时前
AT_arc180_d [ARC180D] Division into 3 题解
数据结构·c++·算法
殷色玫瑰1 小时前
C++ STL:stack、queue、priority_queue 与容器适配器详解
java·开发语言·数据结构·c++·算法·visualstudio
Evand J2 小时前
【电机滤波例程1】PMSM永磁同步电机转速与位置估计,MATLAB程序:标准无迹卡尔曼滤波、模型说明与仿真验证
算法·matlab·电机·ekf·负载·卡尔曼滤波
打码的老程是远篁2 小时前
手把手教你玩转大模型——3. Transformer 的位置编码——模型怎么知道谁在前,谁在后?
人工智能·算法