• CF 1334 E. Divisor Paths (思维、数论)


    题目:传送门

    题意

    给你一个整数D,有一个无向图,图的节点为 D 的因子,若 x % y == 0 && x / y 是一个质数,则节点 x 和 y 有一条无向边,边权为 是 x 的因子但不是 y 的因子的数的个数。有 q 次询问,每次询问输入两个节点 x、y 问节点 x 到节点 y 边权最小的路径有多少条,输出答案对 998244353 取模后的结果。

    1 <= D <= 10^15; 1 <= q <= 3*10^5 ;  1 <= x,y <= D

    思路

    沿着图移动,就是当前点移动到当前点乘以某个质数或者除以某个质数。

    从 x 到 y 的所有最短路径都经过 gcd(x, y)

    答案就是 从 x 移动到 gcd(x, y) 的最短路径条数 乘以 从 y 移动到 gcd(x, y) 的最短路劲的条数。

    从 x 移动到 gcd(x, y) 的最短路径,就是 x 除以 x/gcd(x,y) 的质因子,除的顺序可以随意,那就是求 x/gcd(x,y) 的质因子,然后求一个 多重集合的组合,就是 x 到 gcd(x,y) 最短路径条数。

    从 y 移动到 gcd(x, y) 同理。

    #include <bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    #define lb(x) ((x) & (-(x)))
    using namespace std;
    
    const int N = 1e6 + 5;
    const LL mod = 998244353;
    
    LL ksm(LL a, LL b) {
        LL ans = 1LL;
        while(b) {
            if(b & 1) ans = ans * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return ans;
    }
    
    LL D;
    LL fac[105], ifac[105];
    LL pre[105], tot;
    
    void init() {
    
        fac[0] = 1LL;
        rep(i, 1, 99) fac[i] = fac[i - 1] * i % mod;
        ifac[99] = ksm(fac[99], mod - 2);
        dep(i, 0, 98) ifac[i] = ifac[i + 1] * (i + 1) % mod;
    
        for(LL i = 2; i * i <= D; i++) {
            if(D % i == 0) {
                pre[++tot] = i;
                while(D % i == 0) D /= i;
            }
        }
        if(D > 1) pre[++tot] = D;
    }
    
    void solve() {
        LL x, y;
        scanf("%lld %lld", &x, &y);
    
        int c1 = 0, c2 = 0;
        LL ans = 1LL;
    
        rep(i, 1, tot) {
            int c = 0;
            while(x % pre[i] == 0) {
                x /= pre[i];
                c++;
            }
            while(y % pre[i] == 0) {
                y /= pre[i];
                c--;
            }
    
            if(c > 0) {
                c1 += c;
                ans = ans * ifac[c] % mod;
            }
            else {
                c2 -= c;
                ans = ans * ifac[-c] % mod;
            }
        }
        ans = ans * fac[c1] % mod * fac[c2] % mod;
        printf("%lld
    ", ans);
    }
    
    int main() {
    
        scanf("%lld", &D);
        init();
    
    
        int _; scanf("%d", &_);
        while(_--) solve();
    
    //    solve();
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    Linux 学习手记(4):Linux系统常用Shell命令
    Linux 学习手记(3):Linux基本的文件管理操作
    Nginx的启动、停止与重启
    20个常用正则表达式
    MongoDB增删改查实例
    MongoDB 查询总结
    MongoDB数据库未授权访问漏洞及加固
    MongoDB安装
    java模拟post方式提交表单实现图片上传【转】
    Java图片处理 Thumbnails框架
  • 原文地址:https://www.cnblogs.com/Willems/p/12685133.html
Copyright © 2020-2023  润新知