-
[2022.05.18.] n^m의 약수의 합ALOHA - 2022/ALOHA - 오늘의 문제 (2022 1학기) 2022. 5. 22. 00:00
문제 정보
링크: https://www.acmicpc.net/problem/11693
난이도: Gold II
분류: [수학 → 정수론] [분할 정복 → 분할 정복을 이용한 거듭제곱]
문제 요약
의 약수의 합을 구하면 됩니다. 정말 정직하죠?풀이
을 소인수분해한 결과가 아래와 같다고 합시다.그럼
을 소인수분해한 결과는 자명히 아래와 같게 됩니다.지금부터는 이
를 편의상 라고 재정의하겠습니다.그럼, 약수의 합은 어떻게 구할까요?
만약 위 소인수분해 결과에서
이라면, 약수의 합은 이 됩니다. 라면, 가 됩니다.이를 일반화할 수 있으며,
의 약수의 합은 가 됩니다.그럼 이 문제의 풀이는
을 소인수분해해서 쌍을 얻는 거랑각
쌍에 대해 를 구하는 게 됩니다.앞부분은
을 소인수분해한 뒤 각 지수에 을 곱하는 방식으로 해결할 수 있으며,뒷부분은 분할 정복을 이용한 거듭제곱과 이를 응용한 방식으로 해결할 수 있습니다.
뒷부분의 분할 정복을 요약하자면,
이라고 할 때 가 됩니다.const ll mod = 1e9 + 7; ll fpw(ll a, ll b){ ll res = 1, mul = a, bit = b; while (bit){ if (bit & 1){ res = res*mul % mod; } mul = mul*mul % mod; bit >>= 1; } return res; } ll dnc(ll a, ll b){ if (b == 1){ return 1; } ll bb = b >> 1; ll res = dnc(a, bb); if (b & 1){ ll r1 = res, r2 = res * fpw(a, bb+1) % mod, r3 = fpw(a, bb); return (r1+r2+r3) % mod; } else{ ll r1 = res, r2 = res * fpw(a, bb); return (r1+r2) % mod; } } vector<pl2> v; void Main(){ ll n, m; cin >> n >> m; if (m == 0){ cout << 1; return; } for (ll i = 2; i*i <= n; i++){ if (n%i != 0){ continue; } ll cnt = 0; while (n%i == 0){ n /= i; cnt += m; } v.push_back({i, cnt}); } if (n != 1){ v.push_back({n, m}); } ll ans = 1; for (pl2 pr : v){ ll p = pr.fr, e = pr.sc; ll res = dnc(p, e+1); //cout << p << ' ' << e << " -> " << res << endl; ans *= res; ans %= mod; } cout << ans; }
'ALOHA - 2022 > ALOHA - 오늘의 문제 (2022 1학기)' 카테고리의 다른 글
[2022.04.14.] N과 M (6) (0) 2022.05.21 [2022.04.20.] GALAKSIJA (0) 2022.05.09 [2022.04.17.] 인간-컴퓨터 상호작용 (0) 2022.05.06 [2022.04.11.] A Simple Problem. (0) 2022.05.05