[BOJ/Java] 6902. Orko
π [BOJ/Java] 6902. Orko
π λ¬Έμ λ§ν¬: λ¬Έμ 보기
π λ¬Έμ ν΄μ
Dumitruκ° μ΄μν κΏμ κΎΈκ² λλ€. κΏ μμμ λ¬Έμ΄ μ κΈ΄ λ°©μ κ°ν Dumitruλ nκ°μ λ°μ€λ₯Ό λ°κ²¬νλ©°, κ° λ°μ€μλ mκ°μ μ μκ° μλ€. κ° μ μμλ 1 μ΄μμ μ μκ° μ ν μλ€. κ·Έλ¬λ μ€, λ κ°μ μ μ kμ lμ΄ μ ν μͺ½μ§λ₯Ό λ°κ²¬νκ³ , μͺ½μ§μλ μλμ κ°μ μμ μ νλΌλ μ§μκ° μ ν μλ€.
1λ¨κ³: 첫 λ²μ§Έ λ°μ€λΆν° nλ²μ§Έ λ°μ€κΉμ§ μμλλ‘ κ° λ°μ€μμ ν κ°μ μ μλ₯Ό μ ννλ€. μ νν μ μμ μ«μλ₯Ό λ ΈνΈμ κΈ°λ‘ν ν, ν΄λΉ μ μμ μ«μλ₯Ό 1λ‘ λ³κ²½νλ€.
2λ¨κ³: n-1λ²μ§Έ λ°μ€λΆν° λ λ²μ§Έ λ°μ€κΉμ§ μμμΌλ‘ κ° λ°μ€μμ ν κ°μ μ μλ₯Ό μ ννλ€.
λͺ©νλ λ ΈνΈμ κΈ°λ‘λ μ«μλ€μ κ³±μ΄ kλ‘ λλμ΄ λ¨μ΄μ§λλ‘ νλ μ ν λ°©λ²μ μ΄ κ°μ§μ Tλ₯Ό ꡬνκ³ , Tλ₯Ό lλ‘ λλ λλ¨Έμ§λ₯Ό μΆλ ₯νλ κ²μ΄λ€.
π οΈ νμ΄ κ³Όμ
λ¨Όμ , n, m, k, lκ³Ό κ° λ°μ€μ μ μ κ°λ€μ μ λ ₯λ°λλ€. λ¬Έμ μ ν΅μ¬μ kμ μ½μλ₯Ό μνλ‘ νμ©νλ κ²μ΄λ€. kμ λͺ¨λ μ½μλ₯Ό ꡬν λ€, κ° μ½μμ μΈλ±μ€λ₯Ό λ§€ννμ¬ μν μ μ΄ ν μ΄λΈμ ꡬμ±νλ€.
κ° λ°μ€λ§λ€ μ μ μ νμ κ²½μ°μ μλ₯Ό κ³μ°νλ€. 첫 λ²μ§Έ λ°μ€μ λ§μ§λ§ λ°μ€λ μ μλ₯Ό ν λ²λ§ μ ννλ―λ‘, κ° μ μκ° κΈ°μ¬νλ κ° κ·Έλλ‘ λ°μλλ€.
μ€κ° λ°μ€λ μ μλ₯Ό λ λ² μ ννλ κ²½μ°κ° μμΌλ―λ‘, 첫 λ²μ§Έ μ ν(μ μμ μλ μ«μ κΈ°λ‘)κ³Ό λ λ²μ§Έ μ ν(μ μ μ«μκ° 1λ‘ λ³κ²½λ¨)μ λͺ¨λ κ³ λ €νμ¬ κ²½μ°μ μλ₯Ό λμ νλ€.
λμ κ³νλ²(DP)μ μ΄μ©ν΄ κ° λ°μ€μμ κ³μ°λ κ²½μ°μ μλ₯Ό λμ νλ©°, νμ¬κΉμ§ μ νν μ μλ€μ κ³±μ gcd(k, ·) κ°μ μνλ‘ νννμ¬ μ μ΄λ₯Ό μννλ€.
λͺ¨λ λ°μ€λ₯Ό μ²λ¦¬ν ν, μ΅μ’ μνκ° k(μ¦, kλ‘ λλμ΄ λ¨μ΄μ§λ μν)κ° λλ κ²½μ°μ μλ₯Ό lλ‘ λλ λλ¨Έμ§λ₯Ό μΆλ ₯νλ€.
π» μ½λ ꡬν (Java)
import java.io.*;
import java.util.*;
public class Main {
// μ ν΄λ¦¬λ νΈμ λ²μ μ΄μ©νμ¬ μ΅λ곡μ½μ(GCD)λ₯Ό ꡬνλ λ©μλ
static long gcd(long a, long b) {
// bκ° 0μ΄ λ λκΉμ§ λ°λ³΅
while (b != 0) {
long temp = a % b; // aλ₯Ό bλ‘ λλ λλ¨Έμ§λ₯Ό μμ μ μ₯
a = b; // aμ b κ°μ λμ
b = temp; // bμ λλ¨Έμ§ κ°μ λμ
}
return a; // μ΅λ곡μ½μ λ°ν
}
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 product = (long) dArr[i] * dArr[j];
int g = (int) gcd(product, k);
mult[i][j] = dIndex.get(g);
}
}
// DP λ°°μ΄ μ΄κΈ°ν: dp[i]λ νμ¬ μνκ° dArr[i]μΌ λμ κ²½μ°μ μ
int[] dp = new int[dCount];
// μ΄κΈ° μνλ μ μ μ ν μ κ³±μ΄ 1μΈ μν
dp[dIndex.get(1)] = 1;
// κ° λ°μ€λ₯Ό μμλλ‘ μ²λ¦¬
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 plateValue = Integer.parseInt(st.nextToken());
int g = (int) gcd(plateValue, k);
int idx = dIndex.get(g);
freq[idx]++; // ν΄λΉ μνμ λΉλμ μ¦κ°
}
// νμ¬ λ°μ€μμ μ ν κ°λ₯ν κ²½μ°μ μ λΆν¬λ₯Ό μ μ₯ν λ°°μ΄
int[] boxDist = new int[dCount];
// 첫 λ²μ§Έ λ°μ€μ λ§μ§λ§ λ°μ€λ μ μλ₯Ό ν λ²λ§ μ ννλ―λ‘ λ¨μν freq κ°μ μ¬μ©
if (box == 1 || box == n) {
for (int i = 0; i < dCount; i++) {
boxDist[i] = freq[i] % mod;
}
} else {
// μ€κ° λ°μ€λ μ μλ₯Ό λ λ² μ νν΄μΌ ν¨
// 첫 λ²μ§Έ μ ν: μ μμ μλ μ«μλ₯Ό κΈ°λ‘
// λ λ²μ§Έ μ ν: ν΄λΉ μ μμ μ«μκ° 1λ‘ λ³ν¨
int[] doubleDist = new int[dCount];
// 첫 λ²μ§Έ μ νμ κ²½μ°μ μλ₯Ό μΆκ°
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++) {
long ways;
if (i == j) {
// κ°μ μ μλ₯Ό λ λ² μ ννλ κ²½μ°
ways = (long) freq[i] * (freq[i] - 1);
} else {
// μλ‘ λ€λ₯Έ μ μλ₯Ό μ ννλ κ²½μ°
ways = (long) freq[i] * freq[j];
}
if (ways == 0)
continue;
// λ μ νμ κ²°κ³Ό μνλ₯Ό μν μ μ΄ ν
μ΄λΈμ μ΄μ©ν΄ κ³μ°
int newIndex = mult[i][j];
doubleDist[newIndex] = (int) ((doubleDist[newIndex] + ways) % mod);
}
}
boxDist = doubleDist;
}
// νμ¬κΉμ§μ dp λ°°μ΄κ³Ό νμ¬ λ°μ€μ κ²½μ°μ μ(boxDist)λ₯Ό μ΄μ©νμ¬ μν μ μ΄λ₯Ό μν
int[] nextDP = 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 nextState = mult[i][j]; // μν μ μ΄
nextDP[nextState] = (int) ((nextDP[nextState] + (long) dp[i] * boxDist[j]) % mod);
}
}
// dp λ°°μ΄μ μ
λ°μ΄νΈ
dp = nextDP;
}
// μ΅μ’
μ μΌλ‘ λͺ©ν μν k(μ¦, kλ‘ λλμ΄ λ¨μ΄μ§λ μν)μ κ²½μ°μ μλ₯Ό modλ‘ λλ λλ¨Έμ§λ₯Ό μΆλ ₯
System.out.println(dp[dIndex.get(k)] % mod);
}
β±οΈ μκ° λ³΅μ‘λ λΆμ
λ¬Έμ λ κ° λ°μ€λ§λ€ mκ°μ μ μλ₯Ό μ²λ¦¬νκ³ , kμ μ½μ κ°μλ₯Ό dλΌ ν λ μ 체 μκ° λ³΅μ‘λλ O(n*m + n*d²)μ΄λ€.
nμ μ΅λ 200, mμ μ΅λ 10,000μ΄λ©°, dλ kμ μ½μ κ°μλ‘ λ³΄ν΅ √kμ κ°κΉμ μ ν λ΄μμ μΆ©λΆν κ³μ° κ°λ₯νλ€.
π‘ λλμ
λ¬Έμ ν΄κ²° κ³Όμ μμ κ° λ°μ€μμ μ μ μ νμ λ°λ₯Έ μν μ μ΄λ₯Ό λͺ
ννκ² μ²λ¦¬νλ κ²μ΄ ν΅μ¬μ΄μλ€.
μ μλ‘ κ³Ό gcdλ₯Ό νμ©νμ¬ kμ μ½μλ₯Ό μνλ‘ μ²λ¦¬ν μ , κ·Έλ¦¬κ³ μ€κ° λ°μ€μμ λ λ² μ ννλ κ²½μ°λ₯Ό μΈλ°νκ² κ³ λ €ν μ μ΄ μΈμμ μ΄μλ€.