File Annotation
Not logged in
4fd800b3a8 2011-02-23        kinaba: #include <iostream>
4fd800b3a8 2011-02-23        kinaba: #include <sstream>
4fd800b3a8 2011-02-23        kinaba: #include <iomanip>
4fd800b3a8 2011-02-23        kinaba: #include <vector>
4fd800b3a8 2011-02-23        kinaba: #include <string>
4fd800b3a8 2011-02-23        kinaba: #include <map>
4fd800b3a8 2011-02-23        kinaba: #include <set>
4fd800b3a8 2011-02-23        kinaba: #include <algorithm>
4fd800b3a8 2011-02-23        kinaba: #include <numeric>
4fd800b3a8 2011-02-23        kinaba: #include <iterator>
4fd800b3a8 2011-02-23        kinaba: #include <functional>
4fd800b3a8 2011-02-23        kinaba: #include <complex>
4fd800b3a8 2011-02-23        kinaba: #include <queue>
4fd800b3a8 2011-02-23        kinaba: #include <stack>
4fd800b3a8 2011-02-23        kinaba: #include <cmath>
4fd800b3a8 2011-02-23        kinaba: #include <cassert>
4fd800b3a8 2011-02-23        kinaba: #include <cstring>
4fd800b3a8 2011-02-23        kinaba: using namespace std;
4fd800b3a8 2011-02-23        kinaba: typedef long long LL;
4fd800b3a8 2011-02-23        kinaba: typedef complex<double> CMP;
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba: // mod 演算用ユーティリティ
4fd800b3a8 2011-02-23        kinaba: LL MODVAL = 1000000007LL;
4fd800b3a8 2011-02-23        kinaba: LL ADD(LL x, LL y) { return (x+y)%MODVAL; }
4fd800b3a8 2011-02-23        kinaba: LL SUB(LL x, LL y) { return (x-y+MODVAL)%MODVAL; }
4fd800b3a8 2011-02-23        kinaba: LL MUL(LL x, LL y) { return (x*y)%MODVAL; }
4fd800b3a8 2011-02-23        kinaba: LL POW(LL x, LL e) {
4fd800b3a8 2011-02-23        kinaba:    LL v = 1;
4fd800b3a8 2011-02-23        kinaba:    for(;e;x=MUL(x,x),e>>=1)
4fd800b3a8 2011-02-23        kinaba:       if(e&1)
4fd800b3a8 2011-02-23        kinaba:          v = MUL(v, x);
4fd800b3a8 2011-02-23        kinaba:    return v;
4fd800b3a8 2011-02-23        kinaba: }
4fd800b3a8 2011-02-23        kinaba: LL DIV(LL x, LL y) { return MUL(x, POW(y, MODVAL-2)); }
4fd800b3a8 2011-02-23        kinaba: LL C(LL n, LL k) {
4fd800b3a8 2011-02-23        kinaba:    LL v = 1;
4fd800b3a8 2011-02-23        kinaba:    k = min(k, n-k);
4fd800b3a8 2011-02-23        kinaba:    for(LL i=1; i<=k; ++i)
4fd800b3a8 2011-02-23        kinaba:       v = DIV(MUL(v, n-i+1), i);
4fd800b3a8 2011-02-23        kinaba:    return v;
4fd800b3a8 2011-02-23        kinaba: }
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba: // 本体
4fd800b3a8 2011-02-23        kinaba: class IncreasingNumber { public:
4fd800b3a8 2011-02-23        kinaba:    int countNumbers(long long digits, int divisor)
4fd800b3a8 2011-02-23        kinaba:    {
4fd800b3a8 2011-02-23        kinaba:       LL  N = digits;
4fd800b3a8 2011-02-23        kinaba:       int D = divisor;
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       //  ちょうど N 桁の Increasing number
4fd800b3a8 2011-02-23        kinaba:       //=
4fd800b3a8 2011-02-23        kinaba:       //  0<=Σa<=8 な a[] を使って
4fd800b3a8 2011-02-23        kinaba:       //    1*a[0] + 11*a[1] + ... + 111..111*(a[N-1]+1)
4fd800b3a8 2011-02-23        kinaba:       //  の形で書ける数
4fd800b3a8 2011-02-23        kinaba:       //
4fd800b3a8 2011-02-23        kinaba:       //なので
4fd800b3a8 2011-02-23        kinaba:       //
4fd800b3a8 2011-02-23        kinaba:       //  D で割れるちょうど N 桁の Increasing number の個数
4fd800b3a8 2011-02-23        kinaba:       //=
4fd800b3a8 2011-02-23        kinaba:       //  0<=Σa<=8 な a[] で
4fd800b3a8 2011-02-23        kinaba:       //     coeff[0]*a[0] + coeff[1]*a[1] + ... + coeff[N-1]*(a[N-1]+1) = 0
4fd800b3a8 2011-02-23        kinaba:       //  なものの個数 ( where coeff[i] := "1がi+1個並んだもの" % D )
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       // ステージ1
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       vector<LL> nc(D); // nc[m] = (coeff[i]%D==m な i の数)
4fd800b3a8 2011-02-23        kinaba:       int       ceLast; // coeff[N-1]
4fd800b3a8 2011-02-23        kinaba:       {
4fd800b3a8 2011-02-23        kinaba:          // coeff は高々 D 回でループしてるはず
4fd800b3a8 2011-02-23        kinaba:          vector<int> coeff;
4fd800b3a8 2011-02-23        kinaba:          int loop_start = -1;
4fd800b3a8 2011-02-23        kinaba:          for(int v=1%D ;;)
4fd800b3a8 2011-02-23        kinaba:          {
4fd800b3a8 2011-02-23        kinaba:             loop_start = find(coeff.begin(), coeff.end(), v) - coeff.begin();
4fd800b3a8 2011-02-23        kinaba:             if( loop_start != coeff.size() )
4fd800b3a8 2011-02-23        kinaba:                break;
4fd800b3a8 2011-02-23        kinaba:             coeff.push_back( v );
4fd800b3a8 2011-02-23        kinaba:             v = (v*10 + 1) % D;
4fd800b3a8 2011-02-23        kinaba:          }
4fd800b3a8 2011-02-23        kinaba:          int loop_len = coeff.size() - loop_start;
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:          for(int i=0; i<coeff.size() && i<N; ++i)
4fd800b3a8 2011-02-23        kinaba:             if( i < loop_start )
4fd800b3a8 2011-02-23        kinaba:                nc[coeff[i]] = 1;
4fd800b3a8 2011-02-23        kinaba:             else
4fd800b3a8 2011-02-23        kinaba:                nc[coeff[i]] = (N-i+loop_len-1)/loop_len % MODVAL;
4fd800b3a8 2011-02-23        kinaba:          ceLast = N-1 < loop_start ? coeff[N-1]
4fd800b3a8 2011-02-23        kinaba:                                    : coeff[(N-1-loop_start)%loop_len+loop_start];
4fd800b3a8 2011-02-23        kinaba:       }
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       // ステージ1.5
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       vector< vector<LL> > choice(D, vector<LL>(9));
4fd800b3a8 2011-02-23        kinaba:       for(int m=0; m<D; ++m)
4fd800b3a8 2011-02-23        kinaba:          for(int n=0; n<=8; ++n)
4fd800b3a8 2011-02-23        kinaba:             // nc[m] 種類のものから n 個取る取り方
4fd800b3a8 2011-02-23        kinaba:             choice[m][n] = (n==0 ? 1 : nc[m]==0 ? 0 : C(n+nc[m]-1, nc[m]-1));
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       // ステージ2
4fd800b3a8 2011-02-23        kinaba:       // dp[m][n][q] = 余り [0, 1, ... m] 係数から n 個使って総和を余り q にするやり方は何通り?
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       vector< vector< vector<LL> > > dp(D, vector< vector<LL> >(9, vector<LL>(D)));
4fd800b3a8 2011-02-23        kinaba:       for(int m=0; m<D; ++m)
4fd800b3a8 2011-02-23        kinaba:          dp[m][0][ceLast] = 1;
4fd800b3a8 2011-02-23        kinaba:       for(int n=1; n<=8; ++n)
4fd800b3a8 2011-02-23        kinaba:          dp[0][n][ceLast] = choice[0][n];
4fd800b3a8 2011-02-23        kinaba:       for(int m=1; m<D; ++m)
4fd800b3a8 2011-02-23        kinaba:          for(int n=1; n<=8; ++n)
4fd800b3a8 2011-02-23        kinaba:             for(int q=0; q<D; ++q)
4fd800b3a8 2011-02-23        kinaba:                for(int k=0,q2=q; k<=n; ++k,q2=(q2-m+D)%D)
4fd800b3a8 2011-02-23        kinaba:                   dp[m][n][q] = ADD( dp[m][n][q], MUL( dp[m-1][n-k][q2], choice[m][k] ) );
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba:       LL ans = 0;
4fd800b3a8 2011-02-23        kinaba:       for(int n=0; n<=8; ++n)
4fd800b3a8 2011-02-23        kinaba:          ans = ADD(ans, dp[D-1][n][0]);
4fd800b3a8 2011-02-23        kinaba:       return ans;
4fd800b3a8 2011-02-23        kinaba:    }
4fd800b3a8 2011-02-23        kinaba: };
4fd800b3a8 2011-02-23        kinaba: 
4fd800b3a8 2011-02-23        kinaba: // BEGIN CUT HERE
4fd800b3a8 2011-02-23        kinaba: #include <ctime>
4fd800b3a8 2011-02-23        kinaba: double start_time; string timer()
4fd800b3a8 2011-02-23        kinaba:  { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); }
4fd800b3a8 2011-02-23        kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)
4fd800b3a8 2011-02-23        kinaba:  { os << "{ ";
4fd800b3a8 2011-02-23        kinaba:    for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it)
4fd800b3a8 2011-02-23        kinaba:    os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; }
4fd800b3a8 2011-02-23        kinaba: void verify_case(const int& Expected, const int& Received) {
4fd800b3a8 2011-02-23        kinaba:  bool ok = (Expected == Received);
4fd800b3a8 2011-02-23        kinaba:  if(ok) cerr << "PASSED" << timer() << endl;  else { cerr << "FAILED" << timer() << endl;
4fd800b3a8 2011-02-23        kinaba:  cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } }
4fd800b3a8 2011-02-23        kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock();
4fd800b3a8 2011-02-23        kinaba: #define END    verify_case(_, IncreasingNumber().countNumbers(digits, divisor));}
4fd800b3a8 2011-02-23        kinaba: int main(){
4fd800b3a8 2011-02-23        kinaba: CASE(-2)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 1LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 16;
4fd800b3a8 2011-02-23        kinaba:    int _ = 0;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(-1)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 1LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 1;
4fd800b3a8 2011-02-23        kinaba:    int _ = 9;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(0)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 2LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 12;
4fd800b3a8 2011-02-23        kinaba:    int _ = 4;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(1)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 3LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 111;
4fd800b3a8 2011-02-23        kinaba:    int _ = 9;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(2)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 452LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 10;
4fd800b3a8 2011-02-23        kinaba:    int _ = 0;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(3)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 6LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 58;
4fd800b3a8 2011-02-23        kinaba:    int _ = 38;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(4)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 1000000000000000000LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 500;
4fd800b3a8 2011-02-23        kinaba:    int _ = 0;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: CASE(5)
4fd800b3a8 2011-02-23        kinaba:    long long digits = 26542766498659LL;
4fd800b3a8 2011-02-23        kinaba:    int divisor = 25;
4fd800b3a8 2011-02-23        kinaba:    int _ = 766312864;
4fd800b3a8 2011-02-23        kinaba: END
4fd800b3a8 2011-02-23        kinaba: }
4fd800b3a8 2011-02-23        kinaba: // END CUT HERE