https://www.acmicpc.net/problem/25974
25974번: 거듭제곱의 합 1
$1$부터 $n$까지 모든 자연수의 $p$ 거듭제곱의 합을 $10^9+7$로 나눈 나머지를 구하시오. 다시 말해, $$\left(\sum_{k=1}^{n}k^p\right)\mod\left(10^9+7\right)$$ 을 구하시오.
www.acmicpc.net
[BOJ1492]에서 지수 크기의 상한을 1000으로 높인 버전입니다. 따라서 풀이는 백준 1492번: 합 과 같습니다.
다음은 제 코드입니다.
#include <stdio.h>
#define mod 1000000007
long long array_nCk_modulo[1002][1002]; // array of (nCk) mod (10^9 + 7), 0 <= k,n <= 1001
long long array_sum_of_powers[1001]; // array of (1^K + 2^K + ... + N^K) mod (10^9 + 7), 0 <= K <= 1000
long long power_modular (long long x, long long y); // (x ^ y) mod M
int main() {
long long N, P;
scanf("%lld %lld", &N, &P);
//preprocessing nCk
for (long long i = 0; i <= P + 1; i++) {
array_nCk_modulo[i][0] = array_nCk_modulo[i][i] = 1;
for (long long j = 1; j < i; j++) {
array_nCk_modulo[i][j] = (array_nCk_modulo[i-1][j] + array_nCk_modulo[i-1][j-1]) % mod;
}
}
array_sum_of_powers[0] = N; // 1^0 + 2^0 + ... + N^0 = N
//faulhaber's formula
for (long long i = 1; i <= P; i++) {
long long temp = power_modular(N+1, i+1) - 1;
for (long long j = 0; j <= i - 1; j++) {
temp -= array_nCk_modulo[i+1][j] * array_sum_of_powers[j] % mod;
temp = (temp + mod) % mod;
}
temp = temp * power_modular(array_nCk_modulo[i+1][i], mod - 2) % mod;
array_sum_of_powers[i] = temp;
}
printf("%lld", array_sum_of_powers[P]);
return 0;
}
long long power_modular (long long x, long long y) {
long long result = 1;
while(y > 0) {
if (y & 1) {
result = result * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return result;
}
(C11, 8968KB, 8ms, 제출번호 53638965)
위에서 제가 언급했던 제 블로그의 1492번 포스팅에서, 지수 상한을 1000으로 늘릴 수 있을 것 같다고 했는데 정말 그런 문제가 나와서 깜짝 놀랐습니다. 막상 1000까지 늘려도 8ms인 걸 보면, mod가 작으니까 이항계수 배열을 int 배열로 선언하고 상한을 늘릴 수 있을 것 같습니다. 25974번의 512MB, 1s 제한을 지키려면 대략 10000이 상한일 것 같습니다만...
'분할 정복을 이용한 거듭제곱 > 정수 거듭제곱' 카테고리의 다른 글
백준 26035번: $0101$ (0) | 2023.01.15 |
---|---|
백준 25569번: My뷰 꾸미기 (0) | 2023.01.08 |
백준 1908번: 곱셈 전개식 (0) | 2023.01.07 |
백준 24059번: Function (0) | 2022.01.20 |
백준 13618: RSA (0) | 2021.12.21 |