题解:AT1202Contest_h Incomplete Notes

· · 题解

这题中归中距

实现代码:


#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

// 简化分数表示
struct Fraction {
    long long num, den;  // 分子, 分母

    Fraction(long long n, long long d) {
        if (d == 0) {
            num = 0;
            den = 1;
            return;
        }
        // 确保分母为正
        if (d < 0) {
            n = -n;
            d = -d;
        }
        // 计算最大公约数
        long long g = __gcd(abs(n), abs(d));
        num = n / g;
        den = d / g;
    }

    bool operator==(const Fraction& other) const {
        return num == other.num && den == other.den;
    }
};

// 为Fraction定义哈希函数,使其可以作为unordered_map的键
namespace std {
    template<> struct hash<Fraction> {
        size_t operator()(const Fraction& f) const {
            return hash<long long>()(f.num) ^ hash<long long>()(f.den);
        }
    };
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M;
    cin >> N >> M;

    vector<int> A(N), B(M);
    for (int i = 0; i < N; ++i) {
        cin >> A[i];
    }
    for (int i = 0; i < M; ++i) {
        cin >> B[i];
    }

    // 预计算B中非零元素的位置和值
    vector<pair<int, int>> B_non_zero;
    for (int j = 0; j < M; ++j) {
        if (B[j] != 0) {
            B_non_zero.emplace_back(j, B[j]);
        }
    }

    // 如果B全为0,则所有可能的子序列都满足条件
    if (B_non_zero.empty()) {
        cout << N - M + 1 << endl;
        return 0;
    }

    int count = 0;

    // 检查每个可能的子序列
    for (int i = 0; i <= N - M; ++i) {
        bool valid = true;
        Fraction ratio(1, 1);  // 默认比例
        bool ratio_set = false;

        for (const auto& [j, b_val] : B_non_zero) {
            int a_val = A[i + j];

            // A的当前位置为0,而B的对应位置不为0,无效
            if (a_val == 0) {
                valid = false;
                break;
            }

            // 计算比例 B[j]/A[i+j]
            Fraction current_ratio(b_val, a_val);

            if (!ratio_set) {
                ratio = current_ratio;
                ratio_set = true;
            } else if (ratio != current_ratio) {
                // 比例不一致,无效
                valid = false;
                break;
            }
        }

        // 额外检查:A中有非零元素而B中对应位置为0的情况
        if (valid) {
            for (int j = 0; j < M; ++j) {
                if (B[j] == 0 && A[i + j] != 0) {
                    // 这种情况是允许的,因为我们可以将B[j]替换为任意正实数
                    // 所以不需要标记为无效
                }
            }
        }

        if (valid) {
            count++;
        }
    }

    cout << count << endl;

    return 0;
}