結果
| 問題 |
No.260 世界のなんとか3
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2015-08-01 20:31:04 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
CE
(最新)
AC
(最初)
|
| 実行時間 | - |
| コード長 | 11,238 bytes |
| コンパイル時間 | 500 ms |
| コンパイル使用メモリ | 63,100 KB |
| 最終ジャッジ日時 | 2024-11-14 19:08:06 |
| 合計ジャッジ時間 | 1,143 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
コンパイルエラー時のメッセージ・ソースコードは、提出者また管理者しか表示できないようにしております。(リジャッジ後のコンパイルエラーは公開されます)
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
コンパイルメッセージ
main.cpp:15:3: error: ‘vector’ does not name a type
15 | vector<int> a;
| ^~~~~~
main.cpp:54:10: error: ‘vector’ does not name a type
54 | static vector<int> convert_base(const vector<int>&, int, int);
| ^~~~~~
main.cpp:55:10: error: ‘vector’ does not name a type
55 | static vector<long long> karatsubaMultiply(const vector<long long>&, const vector<long long>&);
| ^~~~~~
main.cpp: In member function ‘void bigint::operator=(const bigint&)’:
main.cpp:60:58: error: ‘a’ was not declared in this scope
60 | void bigint::operator=(const bigint &v) { sign = v.sign; a = v.a; }
| ^
main.cpp:60:64: error: ‘const struct bigint’ has no member named ‘a’
60 | void bigint::operator=(const bigint &v) { sign = v.sign; a = v.a; }
| ^
main.cpp: In member function ‘void bigint::operator=(long long int)’:
main.cpp:64:32: error: ‘a’ was not declared in this scope
64 | for(; v > 0; v = v / base) { a.push_back(v % base); }
| ^
main.cpp: In member function ‘bigint bigint::operator+(const bigint&) const’:
main.cpp:69:43: error: ‘a’ was not declared in this scope
69 | for(int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
| ^
main.cpp:69:55: error: ‘const struct bigint’ has no member named ‘a’
69 | for(int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
| ^
main.cpp:70:23: error: ‘struct bigint’ has no member named ‘a’
70 | if(i == (int) res.a.size()) { res.a.push_back(0); }
| ^
main.cpp:70:39: error: ‘struct bigint’ has no member named ‘a’
70 | if(i == (int) res.a.size()) { res.a.push_back(0);
ソースコード
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
using namespace std;
using i64 = long long;
class range {private: struct I{int x;int operator*(){return x;}bool operator!=(I& lhs){return x<lhs.x;}void operator++(){++x;}};I i,n;
public:range(int n):i({0}),n({n}){}range(int i,int n):i({i}),n({n}){}I& begin(){return i;}I& end(){return n;}};
// base and base_digits must be consistent
const int base = 1000000000;
const int base_digits = 9;
struct bigint {
vector<int> a;
int sign;
bigint(void);
bigint(long long);
bigint(const string&);
void operator = (const bigint&);
void operator = (long long);
bigint operator + (const bigint&) const;
bigint operator - () const;
bigint operator - (const bigint&) const;
bigint operator * (int v) const;
bigint operator * (const bigint&) const;
bigint operator / (int) const;
bigint operator / (const bigint&) const;
int operator % (int) const;
bigint operator % (const bigint&) const;
friend pair<bigint, bigint> divmod(const bigint&, const bigint&);
void operator += (const bigint&);
void operator -= (const bigint&);
void operator *= (int v);
void operator *= (const bigint&);
void operator /= (int);
void operator /= (const bigint&);
bool operator < (const bigint&) const;
bool operator > (const bigint&) const;
bool operator <= (const bigint&) const;
bool operator >= (const bigint&) const;
bool operator == (const bigint&) const;
bool operator != (const bigint&) const;
bigint abs() const;
bool isZero(void) const;
long long longValue() const;
friend bigint gcd(const bigint&, const bigint&);
friend bigint lcm(const bigint&, const bigint&);
bigint pow(int) const;
void trim(void);
void read(const string&);
friend istream& operator >> (istream&, bigint&);
friend ostream& operator << (ostream&, const bigint&);
static vector<int> convert_base(const vector<int>&, int, int);
static vector<long long> karatsubaMultiply(const vector<long long>&, const vector<long long>&);
};
bigint::bigint() : sign(1) {}
bigint::bigint(long long v) { *this = v; }
bigint::bigint(const string &s) { read(s); }
void bigint::operator=(const bigint &v) { sign = v.sign; a = v.a; }
void bigint::operator=(long long v) {
sign = 1;
if(v < 0) { sign = -1, v = -v; }
for(; v > 0; v = v / base) { a.push_back(v % base); }
}
bigint bigint::operator+(const bigint &v) const {
if(sign != v.sign) { return *this - (-v); }
bigint res = v;
for(int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
if(i == (int) res.a.size()) { res.a.push_back(0); }
res.a[i] += carry + (i < (int) a.size() ? a[i] : 0);
carry = res.a[i] >= base;
if(carry) { res.a[i] -= base; }
}
return res;
}
bigint bigint::operator-(const bigint &v) const {
if(sign != v.sign) { return *this + (-v); }
if(abs() < v.abs()) { return -(v - *this); }
bigint res = *this;
for(int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
carry = res.a[i] < 0;
if(carry) { res.a[i] += base; }
}
res.trim();
return res;
}
void bigint::operator*=(int v) {
if(v < 0) { sign = -sign, v = -v; }
for(int i = 0, carry = 0; i < (int) a.size() || carry; ++i) {
if(i == (int) a.size()) { a.push_back(0); }
long long cur = a[i] * (long long) v + carry;
carry = (int) (cur / base);
a[i] = (int) (cur % base);
//asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
}
trim();
}
bigint bigint::operator*(int v) const {
bigint res = *this;
res *= v;
return res;
}
pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
int norm = base / (b1.a.back() + 1);
bigint a = a1.abs() * norm;
bigint b = b1.abs() * norm;
bigint q, r;
q.a.resize(a.a.size());
for(int i = a.a.size() - 1; i >= 0; i--) {
r *= base;
r += a.a[i];
int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
int d = ((long long) base * s1 + s2) / b.a.back();
r -= b * d;
while(r < 0) { r += b, --d; }
q.a[i] = d;
}
q.sign = a1.sign * b1.sign;
r.sign = a1.sign;
q.trim();
r.trim();
return make_pair(q, r / norm);
}
bigint bigint::operator/(const bigint &v) const { return divmod(*this, v).first; }
bigint bigint::operator%(const bigint &v) const { return divmod(*this, v).second; }
void bigint::operator/=(int v) {
if(v < 0) { sign = -sign, v = -v; }
for(int i = (int) a.size() - 1, rem = 0; i >= 0; --i) {
long long cur = a[i] + rem * (long long) base;
a[i] = (int) (cur / v);
rem = (int) (cur % v);
}
trim();
}
bigint bigint::operator/(int v) const {
bigint res = *this;
res /= v;
return res;
}
int bigint::operator%(int v) const {
if(v < 0) { v = -v; }
int m = 0;
for(int i = a.size() - 1; i >= 0; --i) { m = (a[i] + m * (long long) base) % v; }
return m * sign;
}
void bigint::operator+=(const bigint &v) { *this = *this + v; }
void bigint::operator-=(const bigint &v) { *this = *this - v; }
void bigint::operator*=(const bigint &v) { *this = *this * v; }
void bigint::operator/=(const bigint &v) { *this = *this / v; }
bool bigint::operator<(const bigint &v) const {
if(sign != v.sign) { return sign < v.sign; }
if(a.size() != v.a.size()) { return a.size() * sign < v.a.size() * v.sign; }
for(int i = a.size() - 1; i >= 0; i--) { if (a[i] != v.a[i]) { return a[i] * sign < v.a[i] * sign; } }
return false;
}
bool bigint::operator>(const bigint &v) const { return v < *this; }
bool bigint::operator<=(const bigint &v) const { return !(v < *this); }
bool bigint::operator>=(const bigint &v) const { return !(*this < v); }
bool bigint::operator==(const bigint &v) const { return !(*this < v) && !(v < *this); }
bool bigint::operator!=(const bigint &v) const { return *this < v || v < *this; }
void bigint::trim(void) {
while(!a.empty() && !a.back()) { a.pop_back(); }
if(a.empty()) { sign = 1; }
}
bool bigint::isZero(void) const { return a.empty() || (a.size() == 1 && !a[0]); }
bigint bigint::operator-() const {
bigint res = *this;
res.sign = -sign;
return res;
}
bigint bigint::abs() const {
bigint res = *this;
res.sign *= res.sign;
return res;
}
long long bigint::longValue() const {
long long res = 0;
for(int i = a.size() - 1; i >= 0; i--) { res = res * base + a[i]; }
return res * sign;
}
bigint gcd(const bigint &a, const bigint &b) { return b.isZero() ? a : gcd(b, a % b); }
bigint lcm(const bigint &a, const bigint &b) { return a / gcd(a, b) * b; }
void bigint::read(const string &s) {
sign = 1;
a.clear();
int pos = 0;
while(pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
if(s[pos] == '-') { sign = -sign; }
++pos;
}
for(int i = s.size() - 1; i >= pos; i -= base_digits) {
int x = 0;
for(int j = max(pos, i - base_digits + 1); j <= i; j++) { x = x * 10 + s[j] - '0'; }
a.push_back(x);
}
trim();
}
istream& operator>>(istream &stream, bigint &v) {
string s;
stream >> s;
v.read(s);
return stream;
}
ostream& operator<<(ostream &stream, const bigint &v) {
if(v.sign == -1) { stream << '-'; }
stream << (v.a.empty() ? 0 : v.a.back());
for(int i = (int) v.a.size() - 2; i >= 0; --i) { stream << setw(base_digits) << setfill('0') << v.a[i]; }
return stream;
}
vector<int> bigint::convert_base(const vector<int> &a, int old_digits, int new_digits) {
vector<long long> p(max(old_digits, new_digits) + 1);
p[0] = 1;
for(int i = 1; i < (int) p.size(); i++) { p[i] = p[i - 1] * 10; }
vector<int> res;
long long cur = 0;
int cur_digits = 0;
for(int i = 0; i < (int) a.size(); i++) {
cur += a[i] * p[cur_digits];
cur_digits += old_digits;
while(cur_digits >= new_digits) {
res.push_back(int(cur % p[new_digits]));
cur /= p[new_digits];
cur_digits -= new_digits;
}
}
res.push_back((int) cur);
while(!res.empty() && !res.back()) { res.pop_back(); }
return res;
}
vector<long long> bigint::karatsubaMultiply(const vector<long long> &a, const vector<long long> &b) {
int n = a.size();
vector<long long> res(n + n);
if(n <= 32) {
for(int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { res[i + j] += a[i] * b[j]; } }
return res;
}
int k = n >> 1;
vector<long long> a1(a.begin(), a.begin() + k);
vector<long long> a2(a.begin() + k, a.end());
vector<long long> b1(b.begin(), b.begin() + k);
vector<long long> b2(b.begin() + k, b.end());
vector<long long> a1b1 = karatsubaMultiply(a1, b1);
vector<long long> a2b2 = karatsubaMultiply(a2, b2);
for(int i = 0; i < k; i++) { a2[i] += a1[i]; }
for(int i = 0; i < k; i++) { b2[i] += b1[i]; }
vector<long long> r = karatsubaMultiply(a2, b2);
for(int i = 0; i < (int) a1b1.size(); i++) { r[i] -= a1b1[i]; }
for(int i = 0; i < (int) a2b2.size(); i++) { r[i] -= a2b2[i]; }
for(int i = 0; i < (int) r.size(); i++) { res[i + k] += r[i]; }
for(int i = 0; i < (int) a1b1.size(); i++) { res[i] += a1b1[i]; }
for(int i = 0; i < (int) a2b2.size(); i++) { res[i + n] += a2b2[i]; }
return res;
}
bigint bigint::operator*(const bigint &v) const {
vector<int> a6 = convert_base(this->a, base_digits, 6);
vector<int> b6 = convert_base(v.a, base_digits, 6);
vector<long long> a(a6.begin(), a6.end());
vector<long long> b(b6.begin(), b6.end());
while(a.size() < b.size()) { a.push_back(0); }
while(b.size() < a.size()) { b.push_back(0); }
while(a.size() & (a.size() - 1)) { a.push_back(0), b.push_back(0); }
vector<long long> c = karatsubaMultiply(a, b);
bigint res;
res.sign = sign * v.sign;
for(int i = 0, carry = 0; i < (int) c.size(); i++) {
long long cur = c[i] + carry;
res.a.push_back((int) (cur % 1000000));
carry = (int) (cur / 1000000);
}
res.a = convert_base(res.a, 6, base_digits);
res.trim();
return res;
}
bigint bigint::pow(int times) const {
bigint cp = *this;
bigint res(1);
for( ; times>0; times>>=1) {
if(times & 1) { res *= cp; }
cp *= cp;
}
return res;
}
const int mod = int(1e9) + 7;
i64 f(bigint x) {
stringstream ss; ss << x;
string s = ss.str();
int n = s.size();
vector<vector<vector<vector<vector<i64>>>>> dp(n+1, vector<vector<vector<vector<i64>>>>(2, vector<vector<vector<i64>>>(2, vector<vector<i64>>(3, vector<i64>(8)))));
dp[0][0][0][0][0] = 1;
for(int i : range(n)) {
for(int j : range(2)) {
for(int k : range(3)) {
for(int x : range(8)) {
for(int d : range(j?10:s[i]-'0'+1)) {
int flag = j | d < s[i] - '0';
dp[i+1][flag][d==3][(k+d)%3][(x*10+d)%8] += dp[i][j][0][k][x];
dp[i+1][flag][d==3][(k+d)%3][(x*10+d)%8] %= mod;
dp[i+1][flag][1] [(k+d)%3][(x*10+d)%8] += dp[i][j][1][k][x];
dp[i+1][flag][1] [(k+d)%3][(x*10+d)%8] %= mod;
}
}
}
}
}
i64 res = 0;
for(int j : range(2)) {
for(int x : range(1, 8)) {
for(int k : range(3)) {
res = (res + dp[n][j][1][k][x]) % mod;
}
res = (res + dp[n][j][0][0][x]) % mod;
}
}
return res % mod;
}
int main(void) {
bigint a, b; cin >> a >> b;
i64 res = f(b) - f(a-1);
printf("%d\n", (res + mod) % mod);
return 0;
}