F - Nim

F - Nim

Problem Statement

You are given integers $N,A_1,A_2,A_3$. Find the number, modulo $998244353$, of triples of positive integers $(X_1,X_2,X_3)$ that satisfy all of the following three conditions.

  • $1\leq X_i \leq N$ for every $i$.
  • $X_i$ is a multiple of $A_i$ for every $i$.
  • $(X_1 \oplus X_2) \oplus X_3 = 0$, where $\oplus$ denotes bitwise xor.
What is bitwise xor? The bitwise xor of non-negative integers $A$ and $B$, $A \oplus B$, is defined as follows.
  • When $A \oplus B$ is written in binary, the $2^k$s place ($k \geq 0$) is $1$ if exactly one of the $2^k$s places of $A$ and $B$ is $1$, and $0$ otherwise.
For instance, $3 \oplus 5 = 6$ (in binary: $011 \oplus 101 = 110$).

Constraints

  • $1 \leq N \leq 10^{18}$
  • $1 \leq A_i \leq 10$
  • All input values are integers.

Input

The Input is given from Standard Input in the following format:

$N$ $A_1$ $A_2$ $A_3$

Output

Print the answer.  


Sample Input 1

13 2 3 5

Sample Output 1

4

Four triples $(X_1,X_2,X_3)$ satisfy the conditions: $(6,3,5),(6,12,10),(12,6,10),(12,9,5)$.


Sample Input 2

1000000000000000000 1 1 1

Sample Output 2

426724011

Sample Input 3

31415926535897932 3 8 4

Sample Output 3

759934997

 

解题思路

  用刚学的递归写法来做这道数位 dp,请参考数位 dp 学习笔记(灵神模板)

  对 $X_1$,$X_2$ 和 $X_3$ 同时进行数位 dp,找的是满足条件的三元组的数量。很显然由于涉及到异或运算,需要把 $X_i$ 看作是二进制数。考虑参数的选择,由于要满足 $A_i \mid X_i$ 因此还需要用一个参数 $r_i$ 来记录前 $u$ 位所表示的二进制数模 $A_i$ 的值。另外由于询问的区间是 $[1, N]$,所以不可以有前导零。最后在枚举 $X_1$,$X_2$ 和 $X_3$ 第 $u$ 位选择的数 $x_1$,$x_2$,$x_3$ 时,要保证 $x_1 \oplus x_2 \oplus x_3 = 0$。

  一些技巧,事实上并不需要把 $X_i$ 转换成二进制字符串然后 dp,直接用 Xi >> u & 1 来得到 $X_i$ 在二进制下第 $u$ 位的值。由于 $N$ 最大为 $10^{18}$,因此二进制位最多有 $60$ 位,所以一开始传入的参数 $u$ 为 $u=59$,从高位往低位递归,边界条件是 $u = -1$。

  AC 代码如下,时间复杂度为 $O(\log{N} \cdot A^3)$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 60, mod = 998244353;

LL n, a1, a2, a3;
int f[N][10][10][10][2][2][2][2][2][2];

int dfs(int u, int r1, int r2, int r3, int h1, int h2, int h3, int l1, int l2, int l3) {
    if (u < 0) return !r1 && !r2 && !r3 && !l1 && !l2 && !l3;
    if (f[u][r1][r2][r3][h1][h2][h3][l1][l2][l3] != -1) return f[u][r1][r2][r3][h1][h2][h3][l1][l2][l3];
    int ret = 0;
    int up1 = h1 ? n >> u & 1 : 1, up2 = h2 ? n >> u & 1 : 1, up3 = h3 ? n >> u & 1 : 1;
    for (int x1 = 0; x1 <= up1; x1++) {
        for (int x2 = 0; x2 <= up2; x2++) {
            for (int x3 = 0; x3 <= up3; x3++) {
                if (!(x1 ^ x2 ^ x3)) ret = (ret + dfs(u - 1, (r1 * 2 + x1) % a1, (r2 * 2 + x2) % a2, (r3 * 2 + x3) % a3, h1 && x1 == up1, h2 && x2 == up2, h3 && x3 == up3, l1 && !x1, l2 && !x2, l3 && !x3)) % mod;
            }
        }
    }
    return f[u][r1][r2][r3][h1][h2][h3][l1][l2][l3] = ret;
}

int main() {
    scanf("%lld %lld %lld %lld", &n, &a1, &a2, &a3);
    memset(f, -1, sizeof(f));
    printf("%d", dfs(59, 0, 0, 0, 1, 1, 1, 1, 1, 1));
    
    return 0;
}

 

参考资料

  Editorial - GAMEFREAK Programming Contest 2023 (AtCoder Beginner Contest 317):https://atcoder.jp/contests/abc317/editorial/7047

posted @ 2024-01-27 17:34  onlyblues  阅读(7)  评论(0编辑  收藏  举报
Web Analytics