首页 > 其他分享 >Atcoder ABC245H Product Modulo 2

Atcoder ABC245H Product Modulo 2

时间:2024-03-26 15:59:38浏览次数:19  
标签:node Atcoder Product Modulo limits int sum times i64

发现这个 \(m\) 很大,且这个式子是 \(\times\)。
一个想法是拆成 \(m = \prod {p_i}^{e_i}(p_i\in \mathbb{P})\) 然后对于 \(M = p_i^{e_i}\) 依次考虑 \(b_i = a_i\bmod M\) 和 \(N = n\bmod M\)。
根据 \(\text{CRT}\),对于任意一个 \(M\) 得到的不同的 \(b_i\) 对于最后的 \(a_i\) 都是不同的,于是方案数可以直接相乘。

接下来考虑求解 \(M, N\)。
因为最后的 \(b_i\) 是 \(\bmod M\) 意义下的,可以把值域当作 \([1, M]\)。
记 \(f(c, i)\) 为 \(c\) 个 \([1, M]\) 的数乘积 \(p\) 的指数为 \(i\) 的方案数。

首先对于 \(N = 0\),那么就是要求 \(p\) 的指数需要 \(\ge e\),可以考虑容斥,总方案数即为 \(M^k\),不合法的方案数为 \(\sum\limits_{i = 0}^{e - 1} f(k, i)\)。

然后对于 \(N \not = 0\),考虑令 \(N = r\times p^z(p\nmid r)\)。
先得到 \(f(k - 1, i)\),然后用 \(b_k\) 去凑出 \(r\times p^z\)。
那么对于 \(u\times p^x(p\nmid u)\),就需要 \(b_k = v\times p^{z - x}(p\nmid v)\) 满足 \(uv\times p^z\equiv r\times p^z(\bmod M)\)。
一种直观的想法是令 \(v = u^{-1}\times r\),因为 \(p\nmid u\) 肯定存在 \(u^{-1}\)。
进一步,发现 \(v = u^{-1}\times r + kp^{e - x}\) 也是合法的,这是因为后面那部分乘后的结果为 \(uk\times p^e\bmod M = 0\)。
那么就会每 \(p^{e - x}\) 个值就会存在一个合法的 \(v\),就会有 \(p^x\) 个合法的 \(v\)。
于是这部分的方案数为 \(\sum\limits_{i = 0}^e f(k - 1, i)\times p^i\)。

接下来就只需要考虑求 \(f\) 了。
考虑到令 \(g(i)\) 为 \([1, M]\) 范围内的数 \(p\) 的指数为 \(i\) 的方案数,显然有 \(g(i) = \varphi(\frac{M}{p^i})(0\le i\le e)\)。
那么就有转移式 \(f(k, i) = \sum\limits_{j = 0}^i f(k - 1, j)g(i - j)\)。
进一步的,能发现这是卷积形式。
就可以写成 \(G(x) = \sum\limits_{i = 0}^e g(i)x^i\),有 \(F(k, x) = \sum\limits_{i = 0}^e f(k, i)x^i = G^k(x)\)。
那么对多项式做快速幂即可,因为项数是 \(O(\log m)\) 的可以直接暴力乘。

时间复杂度 \(O(\sqrt{m} + \log^2 m\log k)\)。

代码
#include<bits/stdc++.h>
using i64 = long long;
const i64 mod = 998244353;
inline i64 qpow(i64 a, i64 b) {i64 v = 1; a %= mod; while (b) b & 1 && ((v *= a) %= mod), (a *= a) %= mod, b >>= 1; return v;}
struct node_t {
    std::vector<i64> a; int n;
    inline node_t(int n_ = 0) {n = n_, a.resize(n + 1);}
    inline i64 operator [] (int x) const {return a[x];}
    inline i64 &operator [] (int x) {return a[x];}
    inline node_t operator * (const node_t &o) const {
        node_t v(n);
        for (int i = 0; i <= n; i++) for (int j = 0; i + j <= n; j++) (v[i + j] += a[i] * o[j]) %= mod;
        return v;
    }
    inline node_t &operator *= (const node_t &o) {return (*this) = (*this) * o;}
};
node_t qpow(node_t a, i64 b) {
    node_t v(a.n); v[0] = 1;
    while (b) b & 1 && (v *= a, 1), a *= a, b >>= 1;
    return v;
}
int main() {
    i64 k, n, m; scanf("%lld%lld%lld", &k, &n, &m);
    std::map<i64, int> mp;
    for (i64 x = 2; x * x <= m; x++) if (m % x == 0) {
        while (m % x == 0) m /= x, mp[x]++;
    }
    if (m > 1) mp[m] = 1;
    i64 ans = 1;
    for (auto _ : mp) {
        i64 p = _.first; int e = _.second;
        i64 M = 1;
        for (int j = 1; j <= e; j++) M *= p;
        node_t B(e); i64 M_ = M;
        for (int i = 0; i < e; i++) B[i] = (M_ - M_ / p) % mod, M_ /= p;
        B[e] = 1;
        i64 N = n % M, v;
        if (! N) {
            node_t qp = qpow(B, k);
            v = qpow(M, k);
            for (int i = 0; i < e; i++) (v += mod - qp[i]) %= mod;
        } else {
            node_t qp = qpow(B, k - 1);
            int c = 0;
            while (N % p == 0) N /= p, c++;
            v = 0;
            for (int i = 0; i <= c; i++) (v += qp[i] * qpow(p, i)) %= mod;
        }
        (ans *= v) %= mod;
    }
    printf("%lld\n", ans);
    return 0;
}

标签:node,Atcoder,Product,Modulo,limits,int,sum,times,i64
From: https://www.cnblogs.com/rizynvu/p/18096834

相关文章

  • UNIQUE VISION Programming Contest 2024 Spring(AtCoder Beginner Contest 346)
    C我们用\(1\simK\)的和减去出现在\(1\simK\)中的数的和。intn,k,a[N],res;map<int,int>vis;signedmain(){ cin>>n>>k; _for(i,1,n)cin>>a[i]; res=k*(1+k)/2; _for(i,1,n)if(a[i]>=1&&a[i]<=......
  • Atcoder ABC 346 全题解
    闲话上一篇全题解反向不错,如果大家支持我就会继续更。我ABC也打了,ARC也打了,没打好,疯狂掉大分……包括本场比赛也是整整补了EFG三道题,以及ARC死磕D结果使赛后五分钟AC又有素材了……A懒得讲B由于我被B题坑了,所以在此纪念。最简单的方法就是把字符串复制......
  • AtCoder Regular Contest 173 E Rearrange and Adjacent XOR
    洛谷传送门AtCoder传送门不妨考虑最后的结果可以成为哪些\(a_i\)的组合。为了方便分析,我们令\(a_i=2^{i-1}\)。进行一次操作后,所有\(\text{popcount}(a_i)\)都为偶数。所以一个\(x\in[0,2^n-1]\)能被生成出来的必要条件是\(\text{popcount}(x)\)为偶数。然......
  • AtCoder Beginner Contest 346 (ABCDEF)
    AtCoderBeginnerContest346A-AdjacentProduct题意给你一个数组a1,a......
  • Atcoder ABC144E Gluttony
    [ABC144E]Gluttony题面翻译【题目描述】高桥君参加大胃王比赛。比赛由\(N\)人组成的团队为基本单位参赛,高桥君的队伍的队员从\(1\simN\)编号。第\(i\)名队员的消化代价为\(A_i\)。比赛有\(N\)种不同的食物,每位队员需要负责吃掉其中一种食物,不能有两名队员吃同一种......
  • AtCoder Beginner Contest 346 题解
    A-AdjacentProductQuestion给你\(N\)个整数\(A_1,A_2,\dots,A_N\)。同时,定义\(B_i=A_i\timesA_{i+1}\(1\leqi\leqN-1)\)按此顺序打印\(B_1,B_2,\dots,B_{N-1}\)Solution按照题意模拟Code#include<bits/stdc++.h>usingnamespacestd;intmain......
  • AtCoder Beginner Contest 346
    AtCoderBeginnerContest346最刺激的一集。尝试挑战手速极限,用了57s做A。但是好像还是很慢。然后做B,仍然想挑战手速。结果一眼出思路只要把wbwbwwbwbwbw多重复几遍就可以代替「无限长」。很快就写完了。然后交了三发罚时。后来发现我复制若干遍wbwbwwbwbwbw的时候......
  • AtCoder Beginner Contest 346
    A-AdjacentProduct(abc346A)题目大意给定\(n\)个数,依次输出相邻俩数的乘积。解题思路按照题意模拟即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_stdio(false);cin.tie(0);c......
  • Atcoder ABC242H Random Painting
    对于这个\(\max\)似乎没有什么好的办法,考虑\(\min-\max\)反演。记\(t_i\)为第\(i\)格被染黑的时间,有\(E(\max(t_i))=\sum\limits_{S}(-1)^{|S|+1}E(\min(t_i))(i\inS)\)。考虑如果知道了\(S\),那么就可以知道\(c=\sum\limits_{i=1}^m[[l_j,r_j]\capS\no......
  • Atcoder ARC132E Paw
    考虑最后往左走往右走的覆盖情况。能发现肯定是有两个洞之间,或者是第一个洞左边,最后一个洞右边没有被覆盖,而左边的都被覆盖为向左,右边的都被覆盖为向右。大致证明就是考虑左边这一部分,如果有向右的,那么其右边的洞肯定都需要走过才行,不然会被覆盖,那么这样就可以一次性走出左边,就......