[백준 13172] Σ (C#, C++) - soo:bak
작성일 :
문제 링크
설명
M개의 주사위가 있고, 각 주사위의 면 수와 눈의 합이 주어집니다. 모든 주사위를 한 번씩 굴렸을 때 나오는 눈의 합의 기대값을 구하는 문제입니다. 답은 MOD = 1,000,000,007로 나눈 나머지로 출력해야 합니다.
접근법
먼저 각 주사위의 기대값은 눈의 합을 면 수로 나눈 값입니다. 전체 기대값은 각 주사위 기대값의 합이므로, 분수들의 합을 구해야 합니다.
다음으로 모듈러 연산에서 나눗셈은 직접 할 수 없으므로, 분모의 모듈러 역원을 곱합니다. MOD가 소수이므로 페르마 소정리에 의해 N의 역원은 N의 MOD-2 제곱입니다. 빠른 거듭제곱으로 O(log MOD)에 계산할 수 있습니다.
이후 각 주사위마다 S × N의 역원을 구해 더하고, 최종 결과를 MOD로 나눈 나머지를 출력합니다.
Code
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
namespace Solution {
class Program {
const long MOD = 1_000_000_007;
static long PowMod(long a, long e) {
var res = 1L;
while (e > 0) {
if ((e & 1) == 1)
res = res * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return res;
}
static void Main(string[] args) {
var m = int.Parse(Console.ReadLine()!);
var ans = 0L;
for (var i = 0; i < m; i++) {
var parts = Array.ConvertAll(Console.ReadLine()!.Split(), long.Parse);
var n = parts[0];
var s = parts[1] % MOD;
var inv = PowMod(n % MOD, MOD - 2);
ans = (ans + s * inv) % MOD;
}
Console.WriteLine(ans);
}
}
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1'000'000'007LL;
ll powmod(ll a, ll e) {
ll res = 1;
while (e > 0) {
if (e & 1)
res = res * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int m; cin >> m;
ll ans = 0;
for (int i = 0; i < m; i++) {
ll n, s; cin >> n >> s;
ll inv = powmod(n % MOD, MOD - 2);
ans = (ans + (s % MOD) * inv) % MOD;
}
cout << ans % MOD << "\n";
return 0;
}