結果

問題 No.260 世界のなんとか3
ユーザー yuppe19 😺yuppe19 😺
提出日時 2015-08-01 20:31:04
言語 C++11
(gcc 11.4.0)
結果
CE  
(最新)
AC  
(最初)
実行時間 -
コード長 11,238 bytes
コンパイル時間 462 ms
コンパイル使用メモリ 63,344 KB
最終ジャッジ日時 2024-04-27 02:09:15
合計ジャッジ時間 900 ms
ジャッジサーバーID
(参考情報)
judge4 / judge5
このコードへのチャレンジ
(要ログイン)
コンパイルエラー時のメッセージ・ソースコードは、提出者また管理者しか表示できないようにしております。(リジャッジ後のコンパイルエラーは公開されます)
ただし、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); 

ソースコード

diff #

#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;
}
0