Acwing 阿拉丁和飞毯 / LightOJ - 1341(加强数据过后的版本)


这道题因为加强了数据,所以以往大多数题解是过不了了,因为a,b ≤ 1 0 12 \le 10^{12} 1012,我们进行质因数分解,和枚举小于b的且是a的约数这两部分大多数题解都会超时,思路还是以往的思路,但是这里要采用更加优化的算法,而且当我们特判 b ∗ b ≥ a b*b \ge a bba时这儿会爆long long的所以我们需要用__int128来储存 b * b,那么我们这儿用了PR算法对大数进行质因数分解,时间复杂度是 n 1 / 4 n^{1/4} n1/4大大的节约了时间,然后对于枚举小于b的a的约数采用dfs不重不漏的去搜,时间也大大的节省了。

C++ 代码

#include

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long
#define endl "\n"

using namespace std;

const int N = 1e6 + 10, mod = 998244353;

int n, m, k, _;

namespace prime_fac
{
const int S = 8;
int mult_mod(int a, int b, int c)
{
    a %= c, b %= c;
    int ret = 0;
    int tmp = a;
    while (b)
    {
        if (b & 1)
        {
            ret += tmp;
            if (ret > c) ret -= c;
        }
        tmp <<= 1;
        if (tmp > c) tmp -= c;
        b >>= 1;
    }
    return ret;
}
int qow_mod(int a, int n, int _mod)
{
    int ret = 1;
    int temp = a % _mod;
    while (n)
    {
        if (n & 1) ret = mult_mod(ret, temp, _mod);
        temp = mult_mod(temp, temp, _mod);
        n >>= 1;
    }
    return ret;
}
bool check(int a, int n, int x, int t)
{
    int ret = qow_mod(a, x, n);
    int last = ret;
    for (int i = 1; i <= t; i++)
    {
        ret = mult_mod(ret, ret, n);
        if (ret == 1 && last != 1 && last != n - 1) return true;
        last = ret;
    }
    if (ret != 1) return true;
    return false;
}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
bool Miller_Rabin(int n)
{
    if (n < 2) return false;
    if (n == 2) return true;
    if ((n & 1) == 0) return false;
    int x = n - 1;
    int t = 0;
    while ((x & 1) == 0)
    {
        x >>= 1;
        t++;
    }
    for (int i = 0; i < S; i++)
    {
        int a = rng() % (n - 1) + 1;
        if (check(a, n, x, t))
            return false;
    }
    return true;
}
int factor[100];
int tol;
int gcd(int a, int b)
{
    int t;
    while (b)
    {
        t = a;
        a = b;
        b = t % b;
    }
    if (a >= 0) return a;
    return -a;
}
int pollard_rho(int x, int c)
{
    int i = 1, k = 2;
    int x0 = rng() % (x - 1) + 1;
    int y = x0;
    while (1)
    {
        i++;
        x0 = (mult_mod(x0, x0, x) + c) % x;
        int d = gcd(y - x0, x);
        if (d != 1 && d != x) return d;
        if (y == x0) return x;
        if (i == k)
        {
            y = x0;
            k += k;
        }
    }
}
void findfac(int n, int k)
{
    if (n == 1) return;
    if (Miller_Rabin(n))
    {
        factor[tol++] = n;
        return;
    }
    int p = n;
    int c = k;
    while (p >= n) p = pollard_rho(p, c--);
    findfac(p, k);
    findfac(n / p, k);
}
vector fac(int n)
{
    tol = 0;
    vectorret;
    findfac(n, 107);
    for (int i = 0; i < tol; i++)ret.push_back(factor[i]);
    return ret;
}
}
vector > v;
set st;
void dfs(int x,int mul)
{
    if(x == v.size())
    {
        st.insert(mul);
        return;
    }
    int k = 1;
    for(int i = 0; i <= v[x].second; ++i)
    {
        dfs(x+1,mul*k);
        k *= v[x].first;
    }
}
void solve(int op)
{
    cout << "Case " << op << ": ";
    int a, b;
    cin >> a >> b;
    __int128 ag = a, bg = b;
    if(bg*bg >= ag)
    {
        cout << 0 << endl;
        return;
    }
    v.clear();
    vector mp = prime_fac::fac(a);
    int len = mp.size();
    map cp;
    for(int i = 0; i < len; i ++)
    {
        cp[mp[i]]++;
    }
    int res = 1;
    for(auto [x, y] : cp)
    {

        res *= (y+1);
        v.push_back({x,y});
    }
    st.clear();
    res /= 2;
    dfs(0,1);
    for(auto it : st) if(it < b) res--;
    cout << res << endl;

}

signed main()
{
    IOS;
    cin >> _;
    for(int i = 1; i <= _; i ++) solve(i);
    return 0;
}

你可能感兴趣的:(kuangbin-数学,数学,算法)