結果
問題 | No.473 和と積の和 |
ユーザー | @abcde |
提出日時 | 2019-05-10 22:39:07 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 7,538 bytes |
コンパイル時間 | 1,914 ms |
コンパイル使用メモリ | 181,124 KB |
実行使用メモリ | 495,520 KB |
最終ジャッジ日時 | 2024-07-02 01:05:16 |
合計ジャッジ時間 | 10,923 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
12,192 KB |
testcase_01 | AC | 1 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 320 ms
64,128 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 2 ms
5,376 KB |
testcase_13 | AC | 2 ms
5,376 KB |
testcase_14 | AC | 2 ms
5,376 KB |
testcase_15 | AC | 2 ms
5,376 KB |
testcase_16 | AC | 2 ms
5,376 KB |
testcase_17 | AC | 2 ms
5,376 KB |
testcase_18 | AC | 2 ms
5,376 KB |
testcase_19 | AC | 2 ms
5,376 KB |
testcase_20 | AC | 2 ms
5,376 KB |
testcase_21 | AC | 2 ms
5,376 KB |
testcase_22 | AC | 2 ms
5,376 KB |
testcase_23 | AC | 3 ms
5,376 KB |
testcase_24 | AC | 4 ms
5,376 KB |
testcase_25 | AC | 2,832 ms
421,504 KB |
testcase_26 | AC | 191 ms
41,728 KB |
testcase_27 | AC | 374 ms
67,840 KB |
testcase_28 | AC | 2 ms
6,944 KB |
testcase_29 | AC | 33 ms
6,940 KB |
testcase_30 | AC | 26 ms
6,940 KB |
testcase_31 | AC | 20 ms
6,940 KB |
testcase_32 | AC | 14 ms
6,944 KB |
testcase_33 | AC | 4 ms
6,940 KB |
testcase_34 | TLE | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
testcase_37 | -- | - |
testcase_38 | -- | - |
testcase_39 | -- | - |
testcase_40 | -- | - |
testcase_41 | -- | - |
testcase_42 | -- | - |
testcase_43 | -- | - |
testcase_44 | -- | - |
testcase_45 | -- | - |
testcase_46 | -- | - |
ソースコード
// // TODO(TLE版). // #include <bits/stdc++.h> // using namespace std; // using LL = long long; // // // 集合S の 更新. // // @param m: 集合S. // // @return ret: 更新した集合S. // map<vector<LL>, LL> updateSet(map<vector<LL>, LL> m){ // map<vector<LL>, LL> ret; // for(auto &p : m){ // vector<LL> v = p.first; // // for(auto &x : v){ // // LL sq = sqrt(x + 0.0) + 1; // // for(LL a = 1; a < sq + 1; a++){ // // LL b = (x - a) / (1 + a); // // if(b > 0 && a + b + a * b == x){ // // vector<LL> lv = v; // // lv.erase(remove(lv.begin(), lv.end(), x), lv.end()); // // lv.push_back(a); // // lv.push_back(b); // // sort(lv.begin(), lv.end(), greater<LL>()); // // ret[lv]++; // // } // // } // // } // // v[0]のみ確認する方針に変更. // LL x = v[0]; // LL sq = sqrt(x + 0.0) + 1; // // 偶数の場合. // if(x % 2 == 0){ // for(LL a = 2; a <= sq + 1; a += 2){ // LL b = (x - a) / (1 + a); // if(b > 1 && a + b + a * b == x){ // vector<LL> lv = v; // lv.erase(remove(lv.begin(), lv.end(), x), lv.end()); // lv.push_back(a); // lv.push_back(b); // sort(lv.begin(), lv.end(), greater<LL>()); // ret[lv]++; // } // } // } // // 奇数の場合. // if(x % 2 == 1){ // for(LL a = 1; a <= sq + 1; a++){ // LL b = (x - a) / (1 + a); // if(b > 0 && a + b + a * b == x){ // vector<LL> lv = v; // lv.erase(remove(lv.begin(), lv.end(), x), lv.end()); // lv.push_back(a); // lv.push_back(b); // sort(lv.begin(), lv.end(), greater<LL>()); // ret[lv]++; // } // } // } // } // return ret; // } // // int main() { // // // 1. 入力情報取得. // LL N, X; // // cin >> N >> X; // scanf("%llu %llu", &N, &X); // // // 2. N >= 30 の 場合は, 存在しないと判定. // // 2 の 30乗 = 1073741824 > 1e9 であるため. // LL ans = 0; // if(N >= 30){ // cout << ans << endl; // return 0; // } // // // 2. 条件を満たす 集合S を 探索. // // 2-1. N = 2 の場合のロジック. // LL sq = sqrt(X + 0.0) + 1; // map<vector<LL>, LL> m; // for(LL a = 1; a < sq + 1; a++){ // vector<LL> v; // LL b = (X - a) / (1 + a); // if(b > 0 && a + b + a * b == X){ // v.push_back(a); // v.push_back(b); // sort(v.begin(), v.end(), greater<LL>()); // m[v]++; // } // } // // // 2-2. N >= 3 の場合のロジック. // for(int i = 3; i <= N; i++){ // map<vector<LL>, LL> lm = updateSet(m); // swap(m, lm); // } // // for(auto &p : m){ // // auto v = p.first; // // for(auto &i : v) cout << i << " "; // // cout << endl; // // } // // // 4. 出力 ~ 後処理. // // ex. // // 29 805306367 // // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 // // -> の 1通り と思われる. // // 14 147026879 // // -> の 1通り と思われる(3351[ms] かかったので, TLE確定). // // 16 147026879 // // -> の 0通り と思われる(2961[ms] かかったので, TLE確定). // // for(auto &p : m) if(p.first.size() == N) ans++; // // cout << ans << endl; // ans = m.size(); // printf("%llu\n", ans); // return 0; // // } // TODO(速度改善版). #include <bits/stdc++.h> using namespace std; using LL = long long; // Efficient program to print all prime factors of a given number // https://www.geeksforgeeks.org/print-all-prime-factors-of-a-given-number/ // 与えられた正整数についての素因数分解を計算. // @param X: 素因数分解を行う整数. // @return: 素因数分解 の 結果 を 返却. vector<LL> getAllDivisors(LL X) { // 1. X を 2で割り切れなくなるまで割っていく. vector<LL> ret; while(X % 2 == 0) ret.push_back(2), X >>= 1; // 2. X を 3以上の奇数で, 割り切れなくなるまで順次割っていく. for(LL i = 3; i <= sqrt(X); i += 2){ while(X % i == 0){ ret.push_back(i); X /= i; } } // 3. X が 2 より 大きな素数であれば, 追加. if(X > 2) ret.push_back(X); // 4. 出力. return ret; } // 集合S の 更新. // @param m: 集合S. // @param d: 正整数Xを素因数分解した結果から取得した素因数. // @param n: 集合Sの各要素サイズ. // @return ret: 更新した集合S. set<vector<LL>> updateSet(set<vector<LL>> m, LL d, LL n){ // 1. 集合Sの各要素 を 巡回. set<vector<LL>> ret; for(auto &p : m){ // 2. 素因数分解の結果を, 新しいvectorに反映. for(int i = 0; i < n; i++){ vector<LL> v = p; v[i] *= d; sort(v.begin(), v.end()); ret.insert(v); } } // cout << "updateSet d=" << d << endl; // for(auto &p : ret){ // for(auto &v : p) cout << v << " "; // cout << endl; // } // 3. 結果を返却. return ret; } int main() { // 1. 入力情報取得. LL N, X; // cin >> N >> X; scanf("%llu %llu", &N, &X); // 2. X + 1 を 素因数分解. // -> 速度改善が上手く行かなかったので, 解答方針を変更. // -> (a + 1) * (b + 1) = X + 1 の因数分解をベースに考える. vector<LL> divisors = getAllDivisors(X + 1); // ex. // 147026879 + 1 = 147026880 // = 2 * 2 * 2 * 2 * 2 * 2 * 3 * 3 * 3 * 5 * 7 * 11 * 13 * 17 // for(auto &p : divisors) cout << p << " "; // 3. 素因数分解の結果から, (a + 1, b + 1) の組み合わせを全列挙するイメージ. LL ans = 0; LL d = divisors.size(); // 3-1. 集合S の 要素サイズ(N) が大きすぎる場合は, 0個. if(N > d){ cout << ans << endl; return 0; } // 4. 要素 d個をグループ N個に分割. set<vector<LL>> m; vector<LL> v(N, 1); m.insert(v); // 各素因数に関して, 集合S へ 反映. for(auto &d : divisors){ set<vector<LL>> lm = updateSet(m, d, N); swap(m, lm); } // 5. 出力 ~ 後処理. for(auto &p : m){ bool isOne = false; for(auto &v : p){ if(v == 1){ isOne = true; break; } } // 集合S の 要素で, 1 を含むものは, カウント対象から外す. if(!isOne) ans++; } // ex. // 29 805306367 // -> 1通り と思われる(347[ms] かかった). // 6 147026879 // -> 147520通り(323[ms] かかった). // 14 147026879 // -> 1通り と思われる(1012[ms] かかったので, ぎりぎり耐えられるかどうか). // 16 147026879 // -> 0通り と思われる(2[ms] かかった). printf("%llu\n", ans); return 0; }