library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub sash2104/library

:warning: test/atcoder/abc129-f.cpp

Depends on

Code

#include <cassert>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>

// modを可変にする
#define MUTABLE

#include "../../math/modint.hpp"
#include "../../math/matrix.hpp"

using namespace std;
typedef long long ll;

using matrix = Matrix<ModInt>;

int main() {
  ll l, a, b, m;
  cin >> l >> a >> b >> m;
  mod = m;

  // ld[i]に、i桁の要素数を格納する
  vector<ll> ld0(19), ld(19);
  for (int i = 0; i <= 18; ++i) {
    ll x = pow(10, i);
    if (x <= a) continue;
    ll d = (x-a+b-1)/b;
    if (d > l) ld0[i] = l;
    else ld0[i] = d;
    ld[i] = ld0[i];
    if (i > 0) ld[i] -= ld0[i-1];
  }
  matrix q(3);
  q[0][0] = 1; q[1][1] = 1; q[2][2] = 1;
  for (int i = 1; i <= 18; ++i) {
    matrix p(3);
    p[0][0] = pow(10, i); p[0][1] = 0; p[0][2] = 0;
    p[1][0] = 1;          p[1][1] = 1; p[2][2] = 0;
    p[2][0] = 0;          p[2][1] = b; p[2][2] = 1;
    p ^= ld[i];
    q *= p;
  }
  ModInt ans = q[1][0]*ModInt(a)+q[2][0];
  cout << ans.val << endl;
}
#line 1 "test/atcoder/abc129-f.cpp"
#include <cassert>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>

// modを可変にする
#define MUTABLE

#line 1 "math/modint.hpp"
// @title mod int
#line 3 "math/modint.hpp"
using ll = long long;

#ifdef MUTABLE
int mod;
#else
template<int mod>
#endif
struct ModInt {
  int val;
  ModInt inv() const{
    int tmp,a=val,b=mod,x=1,y=0;
    while(b)tmp=a/b,a-=tmp*b,std::swap(a,b),x-=tmp*y,std::swap(x,y);
    return ModInt(x);
  }
  ModInt():val(0){}
  ModInt(ll x){if((val=x%mod)<0)val+=mod;}
  ModInt pow(ll t){ModInt res=1,b=*this; while(t){if(t&1)res*=b;b*=b;t>>=1;}return res;}
  ModInt& operator+=(const ModInt& x){if((val+=x.val)>=mod)val-=mod;return *this;}
  ModInt& operator-=(const ModInt& x){if((val+=mod-x.val)>=mod)val-=mod; return *this;}
  ModInt& operator*=(const ModInt& x){val=(ll)val*x.val%mod; return *this;}
  ModInt& operator/=(const ModInt& x){return *this*=x.inv();}
  bool operator==(const ModInt& x) const{return val==x.val;}
  bool operator!=(const ModInt& x) const{return val!=x.val;}
  bool operator<(const ModInt& x) const{return val<x.val;}
  bool operator<=(const ModInt& x) const{return val<=x.val;}
  bool operator>(const ModInt& x) const{return val>x.val;}
  bool operator>=(const ModInt& x) const{return val>=x.val;}
  ModInt operator+(const ModInt& x) const{return ModInt(*this)+=x;}
  ModInt operator-(const ModInt& x) const{return ModInt(*this)-=x;}
  ModInt operator*(const ModInt& x) const{return ModInt(*this)*=x;}
  ModInt operator/(const ModInt& x) const{return ModInt(*this)/=x;}
  friend std::ostream& operator<<(std::ostream& os, const ModInt& mi) { os << mi.val; return os; }
  static int get_mod() { return mod; }
};

constexpr int MOD10 = 1000000007;
constexpr int MOD99 =  998244353;
#ifndef MUTABLE
using modint = ModInt<MOD10>;
using modint99 = ModInt<MOD99>;
#endif
#line 1 "math/matrix.hpp"
// @title 行列
// 使用例:https://atcoder.jp/contests/abc189/submissions/19676965
#line 6 "math/matrix.hpp"

template< class T >
struct Matrix {
  int H, W;
  std::vector< std::vector< T > > A;
  Matrix() {}
  Matrix(int n, int m) : H(n), W(m), A(H, std::vector< T >(W, 0)) {}
  Matrix(int n) : H(n), W(n), A(H, std::vector< T >(W, 0)) {};
  Matrix(const std::vector<std::vector<T>>& a) : A(a) {
      H = (int)a.size();
      assert(H > 0);
      W = (int)a[0].size();
  }
  int height() const { return H; }
  int width() const { return W; }
  inline const std::vector< T > &operator[](int k) const { return (A.at(k)); }
  inline std::vector< T > &operator[](int k) { return (A.at(k)); }
  static Matrix I(int n) {
    Matrix mat(n);
    for(int i = 0; i < n; i++) mat[i][i] = 1;
    return (mat);
  }

  Matrix &operator+=(const Matrix &B) {
    assert(H == B.H && W == B.W);
    for(int i = 0; i < H; i++)
      for(int j = 0; j < W; j++)
        (*this)[i][j] += B[i][j];
    return (*this);
  }

  Matrix &operator-=(const Matrix &B) {
    assert(H == B.H && W == B.W);
    for(int i = 0; i < H; i++)
      for(int j = 0; j < W; j++)
        (*this)[i][j] -= B[i][j];
    return (*this);
  }

  Matrix &operator*=(const Matrix &B) {
    assert(W == B.H);
    std::vector< std::vector< T > > C(H, std::vector< T >(B.W, 0));
    for(int i = 0; i < H; i++)
      for(int j = 0; j < B.W; j++)
        for(int k = 0; k < W; k++)
          C[i][j] += ((*this)[i][k] * B[k][j]);
    A.swap(C);
    return (*this);
  }

  Matrix &operator^=(long long k) {
    Matrix B = Matrix::I(H);
    while(k > 0) {
      if(k & 1) B *= *this;
      *this *= *this;
      k >>= 1LL;
    }
    A.swap(B.A);
    return (*this);
  }

  std::vector<T> operator*(const std::vector<T> &v) {
    assert(W == (int)v.size());
    std::vector<T> ret(H, 0);
    for(int i = 0; i < H; i++)
      for(int j = 0; j < W; j++)
        ret[i] += ((*this)[i][j] * v[j]);
    return ret;
  }

  Matrix operator+(const Matrix &B) const { return (Matrix(*this) += B); }
  Matrix operator-(const Matrix &B) const { return (Matrix(*this) -= B); }
  Matrix operator*(const Matrix &B) const { return (Matrix(*this) *= B); }
  Matrix operator^(const long long k) const { return (Matrix(*this) ^= k); }

  friend std::ostream &operator<<(std::ostream &os, Matrix &p) {
    for(int i = 0; i < p.H; i++) {
      for(int j = 0; j < p.W; j++) {
        os << p[i][j] << (j + 1 == p.W ? "\n" : " ");
      }
    }
    return (os);
  }
};
#line 12 "test/atcoder/abc129-f.cpp"

using namespace std;
typedef long long ll;

using matrix = Matrix<ModInt>;

int main() {
  ll l, a, b, m;
  cin >> l >> a >> b >> m;
  mod = m;

  // ld[i]に、i桁の要素数を格納する
  vector<ll> ld0(19), ld(19);
  for (int i = 0; i <= 18; ++i) {
    ll x = pow(10, i);
    if (x <= a) continue;
    ll d = (x-a+b-1)/b;
    if (d > l) ld0[i] = l;
    else ld0[i] = d;
    ld[i] = ld0[i];
    if (i > 0) ld[i] -= ld0[i-1];
  }
  matrix q(3);
  q[0][0] = 1; q[1][1] = 1; q[2][2] = 1;
  for (int i = 1; i <= 18; ++i) {
    matrix p(3);
    p[0][0] = pow(10, i); p[0][1] = 0; p[0][2] = 0;
    p[1][0] = 1;          p[1][1] = 1; p[2][2] = 0;
    p[2][0] = 0;          p[2][1] = b; p[2][2] = 1;
    p ^= ld[i];
    q *= p;
  }
  ModInt ans = q[1][0]*ModInt(a)+q[2][0];
  cout << ans.val << endl;
}
Back to top page