結果
問題 | No.28 末尾最適化 |
ユーザー | btk |
提出日時 | 2015-05-07 19:38:39 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 472 ms / 5,000 ms |
コード長 | 1,657 bytes |
コンパイル時間 | 701 ms |
コンパイル使用メモリ | 71,844 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-07-05 19:56:03 |
合計ジャッジ時間 | 1,510 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 472 ms
5,376 KB |
ソースコード
#include<iostream> #include<vector> #include<algorithm> #include<list> using namespace std; #define LL long long const LL mod = 100000009; typedef pair<int, LL> P; int main(void){ LL X[20000]; vector<vector<LL> >POW(40); vector<list<P> > fact(40); int work[40];//素因数分解の作業用配列 //POW[i][K]=i^k<=MODを満たすi,kについてあらかじめ求めておく for (int i = 2; i < 37; i++){ LL num = 1; POW.reserve(40); while (num < mod){ POW[i].push_back(num); num *= i; } POW[i].push_back(num*i); work[i] = i; } //[2,36]について素因数分解 for (int i = 2; i < 37; i++){ if (work[i] != 1){ int p = work[i]; for (int j = p; j < 37; j+=p){ P pf = make_pair(p, 0ll); while (work[j] % p == 0)pf.second++,work[j]/=p; fact[j].push_back(pf); } } } int Q; cin >> Q; while (Q--){ int N, K, B; LL res = mod; cin >> X[0] >> N >> K >> B; N++; for (int i = 1; i < N; i++){ X[i] = ((X[i - 1] * (X[i - 1] + 12345)) % mod)+1; } //Bの素因数pについて,Tに含まれるp^kの最小のkを求める for (auto& pf : fact[B]){ int cnt[40] = { 0 }; int sum = 0; int k = K; //あらかじめ求めておいたべき乗に対する二分探索で一応loglog(10^8)まで落とす for (int i = 0; i < N; i++){ int H = (int)POW[pf.first].size() - 1; int L = 0; while (H - L > 1){ int M = (H + L) / 2; if (X[i] % POW[pf.first][M])H = M; else L = M; } cnt[L]++; } for (int i = 0; i < 40; i++){ sum += min(k, cnt[i])*i; k -= min(k, cnt[i]); } res = min(res, sum / pf.second); } cout << res << endl; } }