結果

問題 No.2744 Power! or +1
ユーザー Naru820
提出日時 2025-02-11 18:10:02
言語 C++14
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 1,074 ms / 3,000 ms
コード長 9,556 bytes
コンパイル時間 2,077 ms
コンパイル使用メモリ 172,348 KB
実行使用メモリ 16,916 KB
最終ジャッジ日時 2025-02-11 18:10:08
合計ジャッジ時間 5,678 ms
ジャッジサーバーID
(参考情報)
judge1 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 9
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// 1e18
const ll INF = 1000000000000000000LL;
// fast modular exponentiation: (base^exp) mod mod
int modExp(int base, int exp, int mod) {
ll result = 1;
ll b = base % mod;
while(exp > 0){
if(exp & 1) result = (result * b) % mod;
b = (b * b) % mod;
exp >>= 1;
}
return (int)result;
}
// T0
// T0 t! N p
// sum_{i>=1} floor(t/p^i) >= v_p(N) t t
int computeT0(int N) {
int temp = N;
vector<pair<int,int>> factors;
// N N ≤ 2e5
for (int p = 2; p*p <= temp; p++){
if(temp % p == 0){
int cnt = 0;
while(temp % p == 0){
cnt++;
temp /= p;
}
factors.push_back({p, cnt});
}
}
if(temp > 1) factors.push_back({temp, 1});
int T0 = 1;
// p^a t
for(auto &pr : factors){
int p = pr.first, cnt = pr.second;
int lo = 1, hi = N; // t N
int best = hi;
while(lo <= hi){
int mid = (lo + hi) / 2;
ll sum = 0;
ll power = p;
while(power <= mid){
sum += mid / power;
if(power > mid / p) break;
power *= p;
}
if(sum >= cnt){
best = mid;
hi = mid - 1;
} else {
lo = mid + 1;
}
}
T0 = max(T0, best);
}
return T0;
}
//
// phase == 0 : XX < T01
// phase == 1 : X r = X mod N 2X ≥ T0
struct State {
ll cost;
int phase; // 0: phase1, 1: phase2
int val; // phase1 X, phase2 r (0 <= r < N)
bool operator>(const State &other) const {
return cost > other.cost;
}
};
//
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, A, B, C;
cin >> N >> A >> B >> C;
// N, A, B, C 2
// T0 1 X < T0
int T0 = computeT0(N);
// T0 N
// 1使1 ≤ x < T0 x! mod N
vector<int> fact_mod(T0, 0);
// 1-indexed index 0 使
fact_mod[1] = 1 % N;
for (int i = 2; i < T0; i++){
fact_mod[i] = (int)(((ll)fact_mod[i-1] * i) % N);
}
// x! T0
// x! ( T0 T0 T0 ) precompute
vector<ll> fact_exact(T0, 0);
fact_exact[1] = 1;
for (int i = 2; i < T0; i++){
// fact_exact[i-1] * i < T0
// T0 T0
if(fact_exact[i-1] > (T0 - 1LL) / i)
fact_exact[i] = T0;
else
fact_exact[i] = fact_exact[i-1] * i;
}
// dp1[x]: 1 () X = x (1 ≤ x < T0)
// dp2[r]: 2 () X mod N = r
vector<ll> dp1(T0, INF);
vector<ll> dp2(N, INF);
// Dijkstra
priority_queue<State, vector<State>, greater<State>> pq;
// X = 1 (1)
dp1[1] = 0;
pq.push({0, 0, 1});
while(!pq.empty()){
State cur = pq.top();
pq.pop();
ll curCost = cur.cost;
int phase = cur.phase;
int curVal = cur.val;
if(phase == 0){ // 1 X (1 ≤ X < T0)
if(curCost != dp1[curVal]) continue; //
// 11: X -> X+1 ( A)
int newX = curVal + 1;
ll newCost = curCost + A;
if(newX < T0){
if(newCost < dp1[newX]){
dp1[newX] = newCost;
pq.push({newCost, 0, newX});
}
} else {
int r = newX % N;
if(newCost < dp2[r]){
dp2[r] = newCost;
pq.push({newCost, 1, r});
}
}
// 2: X -> X^k, k ≥ 2, B^k
// ※ X=1 1^k = 1
if(curVal != 1){
ll power = curVal; // X^1
ll costPow = B; // k=2 costPow B B^2
for (int k = 2; ; k++){
costPow *= B; // costPow = B^k
if(curCost > INF - costPow) break; //
ll nextCost = curCost + costPow;
// X^k power * X < T0 1
if(power <= (T0 - 1LL) / curVal){
ll newVal = power * curVal;
if(newVal < T0){
if(nextCost < dp1[newVal]){
dp1[newVal] = nextCost;
pq.push({nextCost, 0, (int)newVal});
}
power = newVal; // k 使
if(costPow > INF / B) break;
continue;
} else {
// newVal >= T0 2 mod N
int r = modExp(curVal, k, N);
if(nextCost < dp2[r]){
dp2[r] = nextCost;
pq.push({nextCost, 1, r});
}
break;
}
} else {
// 12
int r = modExp(curVal, k, N);
if(nextCost < dp2[r]){
dp2[r] = nextCost;
pq.push({nextCost, 1, r});
}
break;
}
if(costPow > INF / B) break;
}
}
// 3: X -> X! ( C)
// fact_exact, fact_mod
ll fval = fact_exact[curVal];
ll newCostF = curCost + C;
if(fval < T0){
int newX = (int) fval;
if(newCostF < dp1[newX]){
dp1[newX] = newCostF;
pq.push({newCostF, 0, newX});
}
} else {
int r = fact_mod[curVal];
if(newCostF < dp2[r]){
dp2[r] = newCostF;
pq.push({newCostF, 1, r});
}
}
} else { // 2 r (0 ≤ r < N) X ≥ T0
if(curCost != dp2[curVal]) continue;
// r == 0 X N
if(curVal == 0){
cout << curCost << "\n";
return 0;
}
// 11: r -> (r+1) mod N ( A)
int new_r = (curVal + 1) % N;
ll newCost = curCost + A;
if(newCost < dp2[new_r]){
dp2[new_r] = newCost;
pq.push({newCost, 1, new_r});
}
// 2: X -> X^k r -> r^k mod N ( B^k)
// ※ r=0,1
if(curVal != 0 && curVal != 1){
ll expCost = B; // k=2
for (int k = 2; ; k++){
expCost *= B; // expCost = B^k
if(curCost > INF - expCost) break;
ll nextCost = curCost + expCost;
int r_new = modExp(curVal, k, N);
if(nextCost < dp2[r_new]){
dp2[r_new] = nextCost;
pq.push({nextCost, 1, r_new});
}
// k
if(k >= 60) break;
if(expCost > INF / B) break;
}
}
// 3: X! ( C)
// X X ≥ T0 X! N
// ( 0)
ll nextCost = curCost + C;
if(nextCost < dp2[0]){
dp2[0] = nextCost;
pq.push({nextCost, 1, 0});
}
}
}
// dp2[0]
cout << dp2[0] << "\n";
return 0;
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0