[atcoder 349] [F - Subsequence LCM]

fishcanfly發表於2024-04-27

SOS DP 學習筆記
Link here:

程式碼:


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;


public class Main {
    static int n;
    static long m;
    static long[] a;

    public static void readData() throws IOException {
        // init data
        n = rd.nextInt();
        m = rd.nextLong();
        a = new long[n];
        for (int i = 0; i < n; i++) {
            a[i] = rd.nextLong();
        }
    }

    static List<Long> list;

    public static void fenjie() {
        list = new ArrayList<>();
        long num = m;
        for (long i = 2; i * i <= num; i++) {
            if (num % i == 0) {
                long p = 1;
                while (num % i == 0) {
                    num = num / i;
                    p *= i;
                }
                list.add(p);
            }
        }
        if (num > 1) {
            list.add(num);
        }
    }

    static int[] msk;
    static int size;
    static int[] cnt;

    static int sum;

    public static void mask() {
        size = list.size();
        sum = 0;
        msk = new int[n];
        Arrays.fill(msk, -1);
        cnt = new int[1 << size];
        for (int i = 0; i < n; i++) {
            if (m % a[i] == 0) {
                sum++;
                int mask = 0;
                for (int j = 0; j < list.size(); j++) {
                    if (a[i] % list.get(j) == 0) {
                        mask |= (1 << j);
                    }
                }
                cnt[mask]++;
                msk[i] = mask;
            }
        }
    }

    static long[] p;

    public static void init2() {
        p = new long[n + 1];
        p[0] = 1;
        for (int i = 1; i <= n; i++) {
            p[i] = p[i - 1] * 2 % 998244353;
        }
    }

    public static void main(String[] args) throws IOException {
        readData();
        fenjie();
        mask();
        init2();
        // handle special value 1
        if (m == 1) {
            System.out.println(p[sum] - 1);
            return;
        }
        // f[i][j]  前i個狀態中選出或位j的方案數.
        long[] f = new long[1 << size];

        // 前0個狀態選出位為mask的方案數
        f[0] = p[cnt[0]];

        //
        for (int i = 1; i < (1 << size); i++) {
            long[] next = new long[1 << size];
            for (int j = 0; j < (1 << size); j++) {
                next[j] = f[j];
            }
            for (int j = 0; j < (1 << size); j++) {
                if (cnt[i] > 0) {
                    //當前狀態可選
                    next[i | j] += f[j] * (p[cnt[i]] - 1) % 998244353;
                    next[i | j] %= 998244353;
                }
            }
            f = next;
        }

        System.out.println(f[(1 << size) - 1]);
    }

}

class rd {
    static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer tokenizer = new StringTokenizer("");

    // nextLine()讀取字串
    static String nextLine() throws IOException {
        return reader.readLine();
    }

    // next()讀取字串
    static String next() throws IOException {
        while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
        return tokenizer.nextToken();
    }

    // 讀取一個int型數值
    static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    // 讀取一個double型數值
    static double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }

    // 讀取一個long型數值
    static long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    // 讀取一個BigInteger
    static BigInteger nextBigInteger() throws IOException {
        BigInteger d = new BigInteger(rd.nextLine());
        return d;
    }
}

相關文章