C ++ 11, nhiều byte, rất nhanh, wow (1,5 giây trên 1999999998, 0,2 s trên 1 10000 10000)
(Phiên bản Python được đánh gôn bên dưới.)
Chúng tôi bắt đầu với một khái niệm hơi giống với giải pháp của aditsu, nơi chúng tôi tự xây dựng một bộ sưu tập các phần còn lại theo mô-đun có thể tiếp cận trong n bước. Nhưng thay vì đợi cho đến khi chúng tôi tìm thấy phần còn lại 0, chúng tôi kiểm tra hai phần còn lại tìm thấy a và b sao cho a · 10 ^ n + b = 0. Cách tiếp cận giữa chừng này giảm một nửa độ sâu của cây tìm kiếm, vì vậy nó nhanh hơn nhiều về đầu vào lớn và sử dụng ít bộ nhớ hơn.
Một số điểm chuẩn:
$ 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
Mã số:
#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 giây trên 1999999998 với 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()