列表

详情


NC17446. H、Eevee

描述

One day, Eevee received an equation from her best friend:
ax x by = cz,
where c and z are given integers.

She wants to count the number of integral solutions (a,x,b,y) of this equation which satisfies 1≤ a,b ≤ m, 0 ≤ x,y ≤ m.

输入描述

The input starts with one line containing exactly one integer T which is the number of test cases. (1 ≤ T≤ 1000)

Each test case contains one line with three integers c, z and m. (1 ≤ c, m ≤ 105,0 ≤ z ≤ 105)

输出描述

For each test case, output "Case #x: y" in one line (without quotes), where x is the test case number (starting from 1) and y is the number of integral solutions.

示例1

输入:

2
2 2 3
6 2 36

输出:

Case #1: 13
Case #2: 301

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 332ms, 内存消耗: 6056K, 提交时间: 2021-10-06 12:08:09

#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
vector<int> fac[N];
int c , z , m;
int d[10] , e[10] , f[10];
long long res;
vector<pair<int ,int>> factor;

void init() {
    for (int i = 2 ; i < N ; ++ i) {
        if (fac[i].empty()) {
            for (int j = i ; j < N ; j += i) {
                fac[j].emplace_back(i);
            }
        }
    }
}

int power(int A , int p , int e) {
    for (int i = 0 ; i < e ; ++ i) {
        if (1LL * A * p > m) {
            A = m + 1;
            return A;
        } else {
            A *= p;
        }
    }
    return A;
}

void dfs(int k , int A , int B, const int &x , const int &y ) {
    assert(A <= m && B <= m);
    if (k == factor.size()) {
        if (A > 1 && B > 1) {
            ++ res;
        }
    } else {
        int p = factor[k].first , z = factor[k].second;
        // d0 * x + e0 * y = z
        long long a0 = A;
        for (int d0 = 0 ; d0 * x <= z && a0 <= m ; ++ d0 , a0 *= p) {
            if ((z - d0 * x) % y) continue;
            int e0 = (z - d0 * x) / y;
            int b0 = power(B , p, e0);
            if (b0 > m) {
                continue;
            }
            dfs(k + 1 , a0 , b0 , x , y);
        }
    }
}

void exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
    } else {
        exgcd(b, a % b, y, x);
        y -= (a / b) * x;
    }
}

inline int divide(int a , int b) {
    if (a < 0) {
        int c = -a / b + 1;
        return (a + c * b) / b - c;
    } else {
        return a / b;
    }
}

int line(int a , int b , int c) {
    // ax + by = c, 1 <= x,y <= m
    int d = __gcd(a , b);
    if (c % d) return 0;
    a /= d, b /= d, c /= d;

    int X , Y;
    exgcd(a , b , X , Y);
    X *= c , Y *= c;
    assert(a * X + b * Y == c);

    // a (X + kb) + b (Y - ka) = c , k is any int
    int lower = max(divide(1 - X + b - 1, b) , divide(Y - m + a - 1 , a));
    int upper = min(divide(m - X , b) , divide(Y - 1 , a));
    return max(0 , upper - lower + 1);
}

long long work() {
    scanf("%d%d%d" , &c , &z , &m);

    if (c == 1 || z == 0) {
        //a => [1 , m] , b = 0  => m
        //a => 1 , b => [1 , m] => m
        return 4LL * m * m;
    }

    factor.clear();
    for (auto &p : fac[c]) {
        int x = c, y = 0;
        while (x % p == 0) {
            x /= p;
            y += z;
        }
        factor.emplace_back(p , y);
    }
    reverse(factor.begin() , factor.end());

    res = 0;

    // a^x == c^z
    for (int x = 1 ; x <= m ; ++ x) {
        int A = 1 , flag = 1;
        for (auto &it : factor) {
            if (it.second % x) {
                flag = 0;
                break;
            }
            A = power(A , it.first, it.second / x);
            if (A > m) break;
        }
        if (flag && A <= m) {
            res += 4 * m;
        }
    }

    // a, b > 1 && x, y > 0
    int pfirst = factor[0].first , zfirst = factor[0].second;
    for (int d0 = 0 , a0 = 1 ; d0 <= zfirst ; ++ d0, a0 *= pfirst) {
        long long b0 = 1;
        for (int e0 = 0 ; e0 <= zfirst && b0 <= m ; ++ e0, b0 *= pfirst) {
            if (!d0 && !e0) continue;
            bool liner = true;

            int A = a0, B = b0;
            assert(0 < A && A <= m);
            assert(0 < B && B <= m);

            for (int j = 1 ; j < factor.size() ; ++ j) {
                int psecond = factor[j].first;
                int zsecond = factor[j].second;
                for (int dj = 0 , aj = A ; dj <= zsecond ; ++ dj, aj *= psecond) {
                    long long bj = B;
                    for (int ej = 0 ; ej <= zsecond && bj <= m; ++ ej, bj *= psecond) {
                        int delta = d0 * ej - e0 * dj;
                        if (!delta) continue;
                        int dX = zfirst * ej - e0 * zsecond;
                        if (dX % delta) continue;
                        int x = dX / delta;
                        int dY = d0 * zsecond - zfirst * dj;
                        if (dY % delta) continue;
                        int y = dY / delta;
                        if (x < 1 || x > m || y < 1 || y > m) continue;
                        dfs(j + 1 , aj , bj , x , y);
                    }
                    if (1LL * aj * psecond > m) break;
                }

                if (d0 * zsecond % zfirst || e0 * zsecond % zfirst) {
                    liner = false;
                    break;
                }
                d[j] = d0 * zsecond / zfirst;
                e[j] = e0 * zsecond / zfirst;
                A = power(A , psecond, d[j]);
                B = power(B , psecond, e[j]);
                if (A > m || B > m) {
                    liner = false;
                    break;
                }
            }

            if (liner && A > 1 && B > 1) {
                // d0 * x + e0 * y = z
                // x, y [1 , m]
                assert(d0 && e0);
                res += line(d0 , e0 , zfirst);
            }
        }
        if (1LL * a0 * pfirst > m) break;
    }
    return res;
}

int main(int argc, char *argv[]) {
    init();
    int T;
    scanf("%d" , &T);
    while (T --) {
        static int ca = 0;
        printf("Case #%d: %lld\n" , ++ ca, work());
    }
}

上一题