[BOJ/Java] 5266. Strange Dream
π [BOJ/Java] 5266. Strange Dream
π λ¬Έμ λ§ν¬: λ¬Έμ 보기
π λ¬Έμ ν΄μ
Dumitruκ° μ΄μν κΏμ κΏ¨λ€. κΏμμμ λ¬Έμ΄ μ κΈ΄ λ°©μ κ°ν Dumitruλ nκ°μ λ°μ€λ₯Ό λ°κ²¬νλ€. κ° λ°μ€μλ mκ°μ μ μκ° μμκ³ , κ° μ μμλ 1 μ΄μμ μ μκ° μ ν μμλ€. κ·Έλ¬λ μ€ λ κ°μ μ μ kμ lμ΄ μ ν μͺ½μ§λ₯Ό λ°κ²¬νλ€. μͺ½μ§μλ λ€μκ³Ό κ°μ μμ μ νλΌκ³ λμ΄ μμλ€.
1λ¨κ³: 첫 λ²μ§Έ λ°μ€λΆν° nλ²μ§Έ λ°μ€κΉμ§ μμλλ‘ κ° λ°μ€μμ ν κ°μ μ μλ₯Ό μ ννλ€. μ νν μ μμ μ«μλ₯Ό λ ΈνΈμ κΈ°λ‘ν ν, ν΄λΉ μ μμ μ«μλ₯Ό 1λ‘ λ°κΎΌλ€.
2λ¨κ³: n-1λ²μ§Έ λ°μ€λΆν° λ λ²μ§Έ λ°μ€κΉμ§ μμμΌλ‘ κ° λ°μ€μμ ν κ°μ μ μλ₯Ό μ ννλ€.
λͺ©νλ λ ΈνΈμ κΈ°λ‘λ μ«μλ€μ κ³±μ΄ kλ‘ λλμ΄ λ¨μ΄μ§λλ‘ νλ μ ν λ°©λ²μ μ΄ κ°μ§μ Tλ₯Ό ꡬνκ³ , Tλ₯Ό lλ‘ λλ λλ¨Έμ§λ₯Ό μΆλ ₯νλ κ²μ΄λ€.
β ν΅μ¬ κ°λ
- μ μλ‘ κ³Ό gcdλ₯Ό νμ©ν΄ kμ μ½μλ₯Ό μ²λ¦¬νλ€.
- κ° λ°μ€λ³ μ μ μ νμ κ²½μ°μ μλ₯Ό ꡬλΆν΄ κ³μ°νλ€.
- λμ κ³νλ²(DP)μ ν΅ν΄ μν μ μ΄λ₯Ό λμ νλ€.
π οΈ νμ΄ κ³Όμ
λ¨Όμ μ λ ₯μΌλ‘ n, m, k, lκ³Ό κ° λ°μ€μ μ μμ μ ν μλ₯Ό λ°μλ€. kμ λͺ¨λ μ½μλ₯Ό κ΅¬ν΄ κ° μ½μλ₯Ό μνλ‘ μ¬μ©νκ³ , μ½μμ λν μΈλ±μ€λ₯Ό λ§€ννλ€.
κ° λ°μ€λ§λ€ μ μ μ νμ κ²½μ°μ μλ₯Ό κ³μ°νλ€. 첫 λ²μ§Έ λ°μ€μ λ§μ§λ§ λ°μ€λ μ μλ₯Ό ν λ²λ§ μ ννλ―λ‘ κ° μ μκ° κΈ°μ¬νλ κ°μ΄ κ·Έλλ‘ λ°μλμλ€.
μ€κ° λ°μ€λ λ λ² μ ννλ κ²½μ°κ° μμ΄, κ°μ μ μλ₯Ό λ λ² μ ννλ κ²½μ°(λ λ²μ§Έ μ ν μ 1μ΄ κΈ°λ‘λ¨)μ μλ‘ λ€λ₯Έ μ μλ₯Ό μ ννλ κ²½μ°λ₯Ό λͺ¨λ κ³ λ €νλ€.
DP λ°°μ΄μ μ΄μ©ν΄ κ° λ°μ€μμ κ³μ°λ κ²½μ°μ μλ₯Ό λμ νλ©° μν μ μ΄λ₯Ό μ§ννλ€. νμ¬ μνλ μ§κΈκΉμ§ μ νν μ μλ€μ μ«μ κ³±μ gcd(k, ·) κ°μΌλ‘ ννλλ€.
λͺ¨λ λ°μ€λ₯Ό μ²λ¦¬ν ν, μ΅μ’ μνκ° kλ‘ λλμ΄ λ¨μ΄μ§λ κ²½μ°μ μλ₯Ό lλ‘ λλ λλ¨Έμ§λ₯Ό μΆλ ₯νλ€.
π» μ½λ ꡬν (Java)
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
// μ
λ ₯μ μν BufferedReader μ΄κΈ°ν
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 첫 λ²μ§Έ μ€: n (λ°μ€ κ°μ), m (κ° λ°μ€ λΉ μ μ κ°μ) μ
λ ₯
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
// λ λ²μ§Έ μ€: k (λͺ©ν λ°°μ), mod (λλ¨Έμ§ μ°μ° λͺ¨λ) μ
λ ₯
st = new StringTokenizer(br.readLine());
int k = Integer.parseInt(st.nextToken());
int mod = Integer.parseInt(st.nextToken());
// kμ λͺ¨λ μ½μλ₯Ό κ΅¬ν¨ (κ° μνλ₯Ό μ½μλ‘ μ¬μ©)
ArrayList<Integer> dlist = new ArrayList<>();
for (int i = 1; i * i <= k; i++) {
if (k % i == 0) {
dlist.add(i);
if (i * i != k)
dlist.add(k / i);
}
}
// μ½μλ₯Ό μ€λ¦μ°¨μμΌλ‘ μ λ ¬
Collections.sort(dlist);
int dCount = dlist.size();
int[] dArr = new int[dCount];
for (int i = 0; i < dCount; i++) {
dArr[i] = dlist.get(i);
}
// κ° μ½μμ μΈλ±μ€λ₯Ό λ§€ν (μν μ μ΄ ν
μ΄λΈ ꡬμ±μ μ¬μ©)
HashMap<Integer, Integer> dIndex = new HashMap<>();
for (int i = 0; i < dCount; i++) {
dIndex.put(dArr[i], i);
}
// λ μνμ κ³±μ
κ²°κ³Όμ gcd(k, κ³±)μΌλ‘ μ μ΄λλ μνλ₯Ό 미리 κ³μ° (μν μ μ΄ ν
μ΄λΈ)
int[][] mult = new int[dCount][dCount];
for (int i = 0; i < dCount; i++) {
for (int j = 0; j < dCount; j++) {
long prod = (long) dArr[i] * dArr[j];
int g = (int) gcd(prod, k);
mult[i][j] = dIndex.get(g);
}
}
// dp λ°°μ΄ μ΄κΈ°ν (νμ¬ μνλ³ κ²½μ°μ μ μ μ₯)
int[] dp = new int[dCount];
// μ΄κΈ° μνλ 1 (κ³±μ κ²°κ³Όκ° 1)μΈ μνμμ μμ
dp[dIndex.get(1)] = 1;
// κ° λ°μ€λ³λ‘ μ²λ¦¬ (μ΄ nκ°μ λ°μ€)
for (int box = 1; box <= n; box++) {
// κ° λ°μ€ λ΄μμ μ½μ μνμ ν΄λΉνλ μ μ κ°μ μΉ΄μ΄νΈ
int[] freq = new int[dCount];
st = new StringTokenizer(br.readLine());
for (int j = 0; j < m; j++) {
int val = Integer.parseInt(st.nextToken());
int g = (int) gcd(val, k);
int idx = dIndex.get(g);
freq[idx]++; // ν΄λΉ μ½μ μνμ ν΄λΉνλ μ μ κ°μ μ¦κ°
}
// νμ¬ λ°μ€μμ μ νν κ²½μ°μ μλ₯Ό κ³μ°ν λ°°μ΄
int[] boxDist = new int[dCount];
if (box == 1 || box == n) {
// 첫 λ²μ§Έ λ°μ€μ λ§μ§λ§ λ°μ€λ ν λ²λ§ μ ννλ―λ‘ κ·Έλλ‘ μ¬μ©
for (int i = 0; i < dCount; i++) {
boxDist[i] = freq[i] % mod;
}
} else {
// μ€κ° λ°μ€λ λ λ² μ νν¨ (ν λ²μ κΈ°λ‘ ν 1λ‘ λ³κ²½, λ λ² μ ν μ κ³±μ μν₯ μμ)
int[] doubleDist = new int[dCount];
// λ¨Όμ ν λ² μ ννλ κ²½μ° (κΈ°λ³Έμ μΌλ‘ freq κ°μ λν¨)
for (int i = 0; i < dCount; i++) {
doubleDist[i] = (doubleDist[i] + freq[i]) % mod;
}
// λ λ²μ§Έ μ νμ κ²½μ°: κ°μ μ μ λλ λ€λ₯Έ μ μ μ ν κ²½μ° κ³ λ €
for (int i = 0; i < dCount; i++) {
for (int j = 0; j < dCount; j++) {
// iμ jκ° κ°μ κ²½μ°: κ°μ μ μλ₯Ό λ λ² μ ννλ κ²½μ°
// iμ jκ° λ€λ₯Έ κ²½μ°: μλ‘ λ€λ₯Έ μ μλ₯Ό μ ννλ κ²½μ°
long ways = (i == j) ? (long) freq[i] * (freq[i] - 1) : (long) freq[i] * freq[j];
if (ways == 0)
continue;
int idx = mult[i][j];
doubleDist[idx] = (int) ((doubleDist[idx] + ways) % mod);
}
}
boxDist = doubleDist;
}
// νμ¬κΉμ§μ dpμ μ΄λ² λ°μ€μ boxDistλ₯Ό μ΄μ©ν΄ λ€μ μν(ndp)λ₯Ό κ³μ°
int[] ndp = new int[dCount];
for (int i = 0; i < dCount; i++) {
if (dp[i] == 0)
continue;
for (int j = 0; j < dCount; j++) {
if (boxDist[j] == 0)
continue;
int ns = mult[i][j]; // νμ¬ μν iμμ λ°μ€μ μ ν jλ₯Ό μ μ©ν μλ‘μ΄ μν
ndp[ns] = (int) ((ndp[ns] + (long) dp[i] * boxDist[j]) % mod);
}
}
// dp λ°°μ΄ κ°±μ
dp = ndp;
}
// μ΅μ’
μ μΌλ‘ dp λ°°μ΄μμ λͺ©ν μν k (μ¦, μ½μ μνκ° kκ° λλ κ²½μ°)μ κ°μ μΆλ ₯
System.out.println(dp[dIndex.get(k)] % mod);
}
// μ ν΄λ¦¬λ νΈμ λ²μ μ΄μ©ν μ΅λ곡μ½μ(GCD) κ³μ° λ©μλ
static long gcd(long a, long b) {
while (b != 0) {
long t = a % b;
a = b;
b = t;
}
return a;
}
}
β±οΈ μκ° λ³΅μ‘λ λΆμ
λ¬Έμ λ κ° λ°μ€λ§λ€ mκ°μ μ μλ₯Ό μ²λ¦¬νκ³ , kμ μ½μ κ°μλ₯Ό dλΌ ν λ O(n*m + n*d²)μ μκ° λ³΅μ‘λλ₯Ό κ°μ§λ€.
nμ μ΅λ 200, mμ μ΅λ 10,000μ΄λ©°, dλ kμ μ½μ κ°μλ‘ λ³΄ν΅ √kμ κ°κΉμ μ ν λ΄μμ μΆ©λΆν κ³μ°λλ€.
π‘ λλμ
λ¬Έμ μ κ·Ό λ°©μμ κ° λ°μ€μμμ μ μ μ νμ λ°λ₯Έ μν μ μ΄λ₯Ό λͺ
ννκ² μ²λ¦¬νλ λ° μ΄μ μ λμλ€.
μ μλ‘ κ³Ό gcdλ₯Ό νμ©ν΄ kμ μ½μλ₯Ό μ²λ¦¬νλ©° μν μ μ΄ ν
μ΄λΈμ ꡬμ±ν μ μ΄ μΈμμ μ΄λ€.
λμΌν λ°μ€μμ μ μλ₯Ό λ λ² μ ννλ κ²½μ°λ₯Ό μΈλ°νκ² κ³ λ €ν μ μ΄ λ¬Έμ ν΄κ²°μ ν΅μ¬ ν¬μΈνΈμλ€.