※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 3835번 문제인 Alphabet Soup이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/3835
3835번: Alphabet Soup
Peter is having lunch at home. Unfortunately for him, today’s meal is soup. As Peter’s mother is aware that he doesn’t like it very much, she has cooked a special soup using pasta pieces shaped like letters from the alphabet, numbers and other charac
www.acmicpc.net
원형으로 알파벳을 놓을 수 있는 각도들이 정해져있을 때 얼마나 다양하게 알파벳을 배치할 수 있는가를 묻는 문제이다.
먼저 수프를 회전했을 때 처음과 같은 각도들의 배치가 나오게 하는 최소 각도를 구하자. 이는 KMP 알고리즘의 fail함수를 활용해 구해줄 수 있다.
그 다음으로 그만큼의 각도에 놓을 수 있는 총 알파벳의 개수를 이용해 존재할 수 있는 구간의 경우의 수를 구하고, 그러한 구간을 원모양으로 배치하는 경우의 수를 번사이드 보조정리를 이용하여 구하는 것으로 문제를 해결할 수 있다.
1,000,000,007로 나눈 나머지를 구하는 것이 아닌 100,000,007로 나눈 나머지를 구하는 문제임에 유의하자.
또한, 수프를 뒤집어엎으면 안된다는 점에 유의하자.
아래는 제출한 소스코드이다.
#define MOD 100000007
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int arr[360000];
int pi[360000];
ll gcd(ll x, ll y) {
if (y == 0) return x;
return gcd(y, x % y);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
ll N, M; cin >> N >> M;
while (N >= 0) {
memset(arr, 0, sizeof(arr));
memset(pi, 0, sizeof(pi));
for (int m = 0; m < M; m++) {
int x; cin >> x;
arr[x] = 1;
}
for (int i = 0; i < 360000; i++) {
int idx = i;
while (idx > 0) {
if (arr[pi[idx - 1]] == arr[i]) break;
idx = pi[idx - 1];
}
if (idx == 0) pi[i] = 0;
else pi[i] = pi[idx - 1] + 1;
}
ll L = 360000 - pi[359999];
if (360000 % L != 0) L = 360000;
ll beads = 360000 / L;
ll colors = 1;
for (int l = 0; l < L; l++) {
if (arr[l]) colors = (colors * N) % MOD;
}
ll total = 0;
for (ll i = 1; i <= beads; i++) {
ll cur = gcd(i, beads);
ll ret = 1;
ll CC = colors;
while (cur > 0) {
if (cur & 1) ret = (ret * CC) % MOD;
CC = (CC * CC) % MOD;
cur >>= 1;
}
total = (total + ret) % MOD;
}
ll invbeads = 1;
int p = 100000005;
while (p > 0) {
if (p & 1) invbeads = (beads * invbeads) % MOD;
beads = (beads * beads) % MOD;
p >>= 1;
}
cout << (total * invbeads) % MOD << '\n';
cin >> N >> M;
}
}
'BOJ' 카테고리의 다른 글
[BOJ 2565 // C++] 전깃줄 (0) | 2021.10.04 |
---|---|
[BOJ 5557 // C++] 1학년 (0) | 2021.10.03 |
[BOJ 4811 // C++] 알약 (0) | 2021.10.01 |
[BOJ 15961 // C++] 회전 초밥 (0) | 2021.09.30 |
[BOJ 16929 // C++] Two Dots (0) | 2021.09.29 |