C ++ 11, banyak byte, sangat cepat, wow (1,5 detik pada 1999999998, 0,2 detik pada 1… 10.000)
(Versi Python Golf di bawah.)
Kami mulai dengan konsep yang agak mirip dengan solusi aditsu, di mana kami secara induktif membangun koleksi sisa modular yang dapat dicapai dalam n langkah. Tetapi alih-alih menunggu sampai kita menemukan sisa 0, kita memeriksa dua sisa yang ditemukan a dan b sehingga a · 10 ^ n + b = 0. Pendekatan bertemu-di-tengah ini mengurangi kedalaman pohon pencarian, jadi itu adalah jauh lebih cepat pada input besar dan menggunakan memori jauh lebih sedikit.
Beberapa tolok ukur:
$ echo 99999999 | \time ./decbin
1111111122222222333333334444444455555555666666667777777788888889
0.18user 0.01system 0:00.20elapsed 99%CPU (0avgtext+0avgdata 69360maxresident)k
0inputs+0outputs (0major+16276minor)pagefaults 0swaps
$ echo 999999999 | \time ./decbin
111111111222222222333333333444444444555555555666666666777777777888888889
1.22user 0.04system 0:01.27elapsed 100%CPU (0avgtext+0avgdata 434776maxresident)k
0inputs+0outputs (0major+37308minor)pagefaults 0swaps
$ echo 2147483647 | \time ./decbin
4661316525084584315813
0.00user 0.00system 0:00.01elapsed 72%CPU (0avgtext+0avgdata 5960maxresident)k
0inputs+0outputs (0major+1084minor)pagefaults 0swaps
$ echo 1999999998 | \time ./decbin
555555556111111111666666667222222222777777778333333333888888889444444445
1.42user 0.08system 0:01.50elapsed 100%CPU (0avgtext+0avgdata 544140maxresident)k
0inputs+0outputs (0major+38379minor)pagefaults 0swaps
$ \time ./decbin 10000.out
0.19user 0.00system 0:00.20elapsed 100%CPU (0avgtext+0avgdata 3324maxresident)k
0inputs+264outputs (0major+160minor)pagefaults 0swaps
Kode:
#include <algorithm>
#include <boost/iterator/transform_iterator.hpp>
#include <fstream>
#include <list>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using namespace boost;
using namespace std;
static inline bool cmp_first_partnered(pair<int, pair<int, int>> a,
pair<int, pair<int, int>> b) {
return a.first < b.first;
}
static inline bool eq_first_partnered(pair<int, pair<int, int>> a,
pair<int, pair<int, int>> b) {
return a.first == b.first;
}
static pair<int, int> retrace(int modulus, int place, pair<int, int> state,
list<vector<int>>::iterator i,
list<vector<int>>::iterator j, string &ret) {
if (i == j)
return state;
state = retrace(modulus, (place * 10LL) % modulus, state, next(i), j, ret);
int remainder = state.first;
long long k = state.second * 10LL;
if (!binary_search(i->cbegin(), i->cend(), remainder)) {
remainder = ((long long)remainder + modulus - place) % modulus;
k += 1;
}
int digit = k / modulus;
if (digit != 0 || ret.size())
ret += '0' + digit;
return make_pair(remainder, k % modulus);
}
static void mult(int modulus, int x, int y,
vector<pair<int, pair<int, int>>>::iterator i,
vector<pair<int, pair<int, int>>>::iterator j) {
if (y - x == 1) {
for (auto k = i; k != j; k++)
k->first = (k->first * 10LL) % modulus;
return;
}
int z = (x + y) / 2;
vector<pair<int, pair<int, int>>>::iterator k = lower_bound(
i, j, make_pair(int(((long long)modulus * z + 9) / 10), make_pair(0, 0)));
mult(modulus, x, z, i, k);
mult(modulus, z, y, k, j);
inplace_merge(i, k, j,
[](pair<int, pair<int, int>> a, pair<int, pair<int, int>> b) {
return make_pair(a.first, a.second.second) <
make_pair(b.first, b.second.second);
});
}
static string go(int modulus) {
if (modulus == 1)
return "1";
int sequence = 1;
list<vector<int>> v = {{0}};
vector<pair<int, pair<int, int>>> partnered;
int place = 1;
while (true) {
v.emplace_back(v.rbegin()->size() * 2);
vector<int> &previous = *next(v.rbegin()), ¤t = *v.rbegin();
auto offset = [modulus, place, sequence](int a) {
return (a + (long long)place) % modulus;
};
auto old_mid =
lower_bound(previous.cbegin(), previous.cend(), modulus - place),
new_mid = lower_bound(previous.cbegin(), previous.cend(), place);
current.resize(
set_union(new_mid, previous.cend(),
make_transform_iterator(previous.cbegin(), offset),
make_transform_iterator(old_mid, offset),
set_union(previous.cbegin(), new_mid,
make_transform_iterator(old_mid, offset),
make_transform_iterator(previous.cend(), offset),
current.begin())) -
current.begin());
int place2 = modulus - (long long)place * place % modulus;
auto offset_partnered = [modulus, place, place2,
sequence](pair<int, pair<int, int>> a) {
return make_pair((a.first + (long long)place2) % modulus,
make_pair((a.second.first + (long long)place) % modulus,
sequence + a.second.second));
};
auto old_mid_partnered =
lower_bound(partnered.cbegin(), partnered.cend(),
make_pair(modulus - place2, make_pair(0, 0))),
new_mid_partnered = lower_bound(partnered.cbegin(), partnered.cend(),
make_pair(place2, make_pair(0, 0)));
vector<pair<int, pair<int, int>>> next_partnered(partnered.size() * 2 + 1);
auto i =
set_union(partnered.cbegin(), new_mid_partnered,
make_transform_iterator(old_mid_partnered, offset_partnered),
make_transform_iterator(partnered.cend(), offset_partnered),
next_partnered.begin(), cmp_first_partnered);
if (new_mid_partnered == partnered.cend() ||
new_mid_partnered->first != place2)
*i++ = make_pair(place2, make_pair(place, sequence));
next_partnered.resize(
set_union(new_mid_partnered, partnered.cend(),
make_transform_iterator(partnered.cbegin(), offset_partnered),
make_transform_iterator(old_mid_partnered, offset_partnered),
i, cmp_first_partnered) -
next_partnered.begin());
partnered.swap(next_partnered);
sequence += previous.size();
place = (place * 10LL) % modulus;
mult(modulus, 0, 10, partnered.begin(), partnered.end());
partnered.resize(
unique(partnered.begin(), partnered.end(), eq_first_partnered) -
partnered.begin());
auto with_first = [](int a) { return make_pair(a, make_pair(a, 0)); };
vector<pair<int, pair<int, int>>> hits;
set_intersection(partnered.cbegin(), partnered.cend(),
make_transform_iterator(current.cbegin(), with_first),
make_transform_iterator(current.cend(), with_first),
back_inserter(hits), cmp_first_partnered);
if (hits.size()) {
pair<int, pair<int, int>> best = *min_element(
hits.begin(), hits.end(),
[](pair<int, pair<int, int>> a, pair<int, pair<int, int>> b) {
return a.second.second < b.second.second;
});
string ret = "";
pair<int, int> state =
retrace(modulus, 1, make_pair(best.second.first, 0), v.begin(),
prev(v.end()), ret);
retrace(modulus, 1, make_pair(best.first, state.second), v.begin(),
prev(v.end()), ret);
return ret;
}
}
}
int main(int argc, const char *argv[]) {
ios_base::sync_with_stdio(false);
if (argc >= 2) {
ofstream ofs(argv[1]);
for (int modulus = 1; modulus <= 10000; modulus++)
ofs << go(modulus) << '\n';
} else {
int modulus;
cin >> modulus;
cout << go(modulus) << '\n';
}
return 0;
}
Python, 280 byte (8,6 detik pada 1999999998 dengan PyPy)
n=input()
if n<2:print 1;exit()
d={0:0}
l=[]
k=1
b=x=y=0
while 1:
for a in[0]+l:
m=(a+k)%n
if m not in d:l.append(m);d[m]=b
k=(k*10)%n;b+=1
for a in l:
if(-k*a)%n in d:
while(a-x)%n:x+=10**d[(a-x)%n]
while(-y-k*a)%n:y+=10**d[(-y-k*a)%n]
print(10**b*x+y)/n;exit()