zoukankan      html  css  js  c++  java
  • 九校联考(DL24凉心模拟) 整除(中国剩余定理+原根性质)

    题意简述

    给定 (n, m),求 (n|x^m - x) 在满足 (x in [1, n]) 时合法的 (x) 的数量。答案模 (998244353)。单个测试点包含多组数据。
    其中 (n) 由如下方式给出:

    • 给定 (c) 个不超过 (t) 的质数 (p_i(i in [1, c])),有 (n = prod_limits{i = 1}^c p_i)

    所有测试数据满足 (1 leq c leq 50,1 leq t leq 10^4,1 leq m leq 10^9),数据组数 (leq 10000)

    题解

    首先,由于已经给出了 (n) 的唯一分解式 (n = p_1p_2cdots p_c),故我们可以将 (n | x^m - x) 这个式子拆成由 (c) 个形如 (x^m equiv x ({ m mod} p_i)) 的同余方程组成的同余方程组。

    我们先对第 (i) 个方程求出 ([1, p_i]) 内满足条件的数的数量,记为 (s_i)。显然这些解 ({ m mod} p_i) 均不相同,故 (s_i)(x)({ m mod} p_i) 意义下的合法余数的数量。由于所有 (p_i) 均为互不相同的质数,即两两互质,因此可以证明,除了 (1) 为公共解外,任意两个方程的解(([1, p_i]) 范围内)不存在交集。因此,我们在每个方程中任选一个解,构造一个新的一次同余方程组,共能得到 (prod s_i) 个不同的方程组。由于根据中国剩余定理,每个方程组在 ([1, n]) 范围内仅有唯一解,因此答案就为 (prod s_i)

    所以,对于第 (i) 个方程,我们需要求 (s_i = sum_limits{x = 1}^p[x ^ m equiv x{ m mod }p])

    存在一种做法是使用线性筛在接近线性的时间内求所有 ([1, p_i]) 内的数的 (m) 次幂,然后暴力判断。不过这里,介绍一种更简单的方法。

    首先给出以下结论:给定 (m)(p),且 (p) 为质数,那么有:

    [left(sum_{x = 1}^p[x ^ m equiv x{ m mod }p] ight) = { m gcd}(m - 1, p - 1) + 1 ]

    证明如下:

    我们要求满足 (x in [1, p])(x^m equiv x ({ m mod} p))(x) 的个数。

    首先 (x = p) 一定满足,故不特殊考虑,最后答案 (+1) 即可。接下来只考虑 (x in [1, p - 1]) 的情况。由于 (p) 为质数,因此 (p) 存在一个原根 (g)([1, p - 1]) 内的任意数在 ({ m mod} p) 意义下都可以表示为 (g^y) 的形式。这样,原方程就转化为:

    [g^{my} equiv g^y ({ m mod} p) ]

    根据费马小定理:

    [my equiv y ({ m mod} p - 1) Rightarrow (m - 1)y equiv 0 ({ m mod} p - 1) ]

    (k = gcd(m - 1, p - 1)),两边同时除以 (k),得:

    [frac{m - 1}{k}y equiv 0 ({ m mod} frac{p - 1}{k}) ]

    由于此时 (gcd(frac{m - 1}{k}, frac{p - 1}{k}) = 1),因此 (y) 一定有 (frac{p - 1}{k} | y)。由于 (y in [0, p - 2]),显然,(frac{p - 1}{k}) 的任意小于 (k) 的非负整数倍((0 hicksim k - 1) 倍)均满足条件,因此 (y) 共有 (k) 种合法取值。

    因此满足 (sum_{x = 1}^p[x ^ m equiv x{ m mod }p])(i) 共有 (k + 1) 个。

    这样,本题的时间复杂度就从 (O(sum p_i)) 优化至了 (O(c imes log p_i))(log)(gcd) 的复杂度)。

    代码

    线性筛求幂后暴力判断代码如下(常数莫名其妙很大...)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define rg register
    
    const int e = 998244353, N = 1e4 + 10;
    
    int mod, c, m;
    
    inline void add(rg int& x, rg int y) {
      x += y, x -= x >= mod ? mod : 0;
    }
    
    inline void mul(rg int& x, rg int y) {
      x = 1ull * x * y % mod;
    }
    
    inline int qpow(rg int v, rg int p) {
      rg int res = 1;
      for (; p; p >>= 1, mul(v, v)) {
        if (p & 1) {
          mul(res, v);
        }
      }
      return res;
    }
    
    inline int solve(rg int n) {
      rg int p[N], f[N], pri[N], t;
      mod = n, t = 0;
      fill(p + 1, p + 1 + n, 1);
      rg int res = 2;
      for (rg int i = 2; i < n; ++i) {
        if (p[i]) {
          pri[++t] = i, f[i] = qpow(i, m);
        }
        res += (i == f[i]);
        for (rg int j = 1, d; j <= t && (d = i * pri[j]) <= n; ++j) {
          p[d] = 0;
          f[d] = 1ull * f[i] * f[pri[j]] % mod;
          if (i % pri[j] == 0) {
            break;
          }
        }
      }
      return res;
    }
    
    int main() {
      int T; scanf("%*d%d", &T);
      for (rg int kase = 1; kase <= T; ++kase) {
        scanf("%d%d", &c, &m);
        rg int ans = 1;
        for (rg int i = 1; i <= c; ++i) {
          rg int x; scanf("%d", &x);
          rg int v = solve(x);
          mod = e, mul(ans, v);
        }
        printf("%d
    ", ans);
      }
      return 0;
    }
    

    用更简单的方法代码如下:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define rg register
    
    const int mod = 998244353;
    
    inline void mul(int& x, int y) {
      x = 1ll * x * y % mod;
    }
    
    int main() {
      int T; scanf("%*d%d", &T);
      for (rg int kase = 1; kase <= T; ++kase) {
        int n, m; scanf("%d%d", &n, &m);
        int ans = 1;
        for (rg int i = 1; i <= n; ++i) {
          int x; scanf("%d", &x);
          mul(ans, __gcd(m - 1, x - 1) + 1);
        }
        printf("%d
    ", ans);
      }
      return 0;
    }
    
  • 相关阅读:
    Linux下打包发布Qt应用程序
    嵌入式中的BSP---BSP到底是什么?
    (转)Spring 工具类 ConfigurationClassParser 分析得到配置类 -- springboot一样处理过程
    React Hooks之useState、useEffect使用
    数组排序多种方法汇总
    封装判断浏览器是否是IE浏览器
    封装addEventListener,removeEventListener指定元素添加事件及兼容问题js
    js判断是否超过几行
    react日期格式化组件
    Windows smynesc免费经典儿时小游戏分享给大家
  • 原文地址:https://www.cnblogs.com/ImagineC/p/9880891.html
Copyright © 2011-2022 走看看