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;
}
}