ADDED SRM/550-U/1C.cpp Index: SRM/550-U/1C.cpp ================================================================== --- SRM/550-U/1C.cpp +++ SRM/550-U/1C.cpp @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex CMP; + +static const int MODVAL = 1000000007; +struct mint +{ + int val; + mint():val(0){} + mint(int x):val(x%MODVAL) {} + mint(size_t x):val(x%MODVAL) {} + mint(LL x):val(x%MODVAL) {} +}; +mint& operator+=(mint& x, mint y) { return x = x.val+y.val; } +mint& operator*=(mint& x, mint y) { return x = LL(x.val)*y.val; } +mint operator+(mint x, mint y) { return x+=y; } +mint operator*(mint x, mint y) { return x*=y; } + +template +vector MATMUL(const vector< vector >& a, const vector& v) +{ + int N = a.size(); + vector u(N); + for(int i=0; i +vector< vector > MATMUL(const vector< vector >& a, const vector< vector >& b) +{ + int N = a.size(); + vector< vector > c(N, vector(N)); + for(int i=0; i +vector< vector > MATPOW(vector< vector > a, LL e) +{ + int N = a.size(); + vector< vector > c(N, vector(N)); + for(int i=0; i>=1) { + if(e&1) + c = MATMUL(c, a); + a = MATMUL(a, a); + } + return c; +} + +class ConversionMachine { public: + int countAll(string word1, string word2, vector costs, int maxCost) + { + int d[3] = {}; + LL minCost = 0; + for(int i=0; i maxCost ) + return 0; + LL c3 = accumulate(costs.begin(), costs.end(), 0LL); + return solve(d, (maxCost-minCost)/c3*3+d[1]*1+d[2]*2).val; + } + + mint solve(int d[3], int rem) + { + int n = d[0]+d[1]+d[2]; + + map, int> enc; + for(int b=0,id=0; b<=n; ++b) + for(int c=0; b+c<=n; ++c,++id) + enc[make_pair(b,c)] = id; + int D = enc.size(); + + vector< vector > M(D+1, vector(D+1)); + for(int b=0; b<=n; ++b) + for(int c=0; b+c<=n; ++c) + { + int a = n-b-c; + if(a) { + M[enc[make_pair(b,c+1)]][enc[make_pair(b,c)]] = a; + } + if(b) { + M[enc[make_pair(b-1,c)]][enc[make_pair(b,c)]] = b; + if(b-1==0 && c==0) + M.back()[enc[make_pair(b,c)]] = b; + } + if(c) { + M[enc[make_pair(b+1,c-1)]][enc[make_pair(b,c)]] = c; + } + } + M.back().back() = 1; + + vector V(D+1); + V[enc[make_pair(d[1],d[2])]] = 1; + V.back() = V[0]; + + return MATMUL(MATPOW(M, rem), V).back(); + } +}; + +// BEGIN CUT HERE +#include +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template ostream& operator<<(ostream& os, const vector& v) + { os << "{ "; + for(typename vector::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const int& Expected, const int& Received) { + bool ok = (Expected == Received); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, ConversionMachine().countAll(word1, word2, costs, maxCost));} +int main(){ + +CASE(0) + string word1 = "a"; + string word2 = "b"; + int costs_[] = {100,2,3}; + vector costs(costs_, costs_+sizeof(costs_)/sizeof(*costs_)); + int maxCost = 205; + int _ = 2; +END +CASE(1) + string word1 = "abcba"; + string word2 = "abcba"; + int costs_[] = {67,23,43}; + vector costs(costs_, costs_+sizeof(costs_)/sizeof(*costs_)); + int maxCost = 0; + int _ = 1; +END +CASE(2) + string word1 = "cccccccc"; + string word2 = "aaaaaaaa"; + int costs_[] = {10000000,1,1}; + vector costs(costs_, costs_+sizeof(costs_)/sizeof(*costs_)); + int maxCost = 100; + int _ = 40320; +END +CASE(3) + string word1 = "aa"; + string word2 = "cc"; + int costs_[] = {1,10,100}; + vector costs(costs_, costs_+sizeof(costs_)/sizeof(*costs_)); + int maxCost = 1787; + int _ = 123611681; +END +/* +CASE(4) + string word1 = ; + string word2 = ; + int costs_[] = ; + vector costs(costs_, costs_+sizeof(costs_)/sizeof(*costs_)); + int maxCost = ; + int _ = ; +END +CASE(5) + string word1 = ; + string word2 = ; + int costs_[] = ; + vector costs(costs_, costs_+sizeof(costs_)/sizeof(*costs_)); + int maxCost = ; + int _ = ; +END +*/ +} +// END CUT HERE Index: lib/numeric/modArith.cpp ================================================================== --- lib/numeric/modArith.cpp +++ lib/numeric/modArith.cpp @@ -36,10 +36,47 @@ for(int kk=1; kk +vector MATMUL(const vector< vector >& a, const vector& v) +{ + int N = a.size(); + vector u(N); + for(int i=0; i +vector< vector > MATMUL(const vector< vector >& a, const vector< vector >& b) +{ + int N = a.size(); + vector< vector > c(N, vector(N)); + for(int i=0; i +vector< vector > MATPOW(vector< vector > a, LL e) +{ + int N = a.size(); + vector< vector > c(N, vector(N)); + for(int i=0; i>=1) { + if(e&1) + c = MATMUL(c, a); + a = MATMUL(a, a); + } + return c; +} /* // MODVAL must be a prime!! LL GSS(LL k, LL b, LL e) // k^b + k^b+1 + ... + k^e { @@ -46,30 +83,10 @@ if( b > e ) return 0; if( k <= 1 ) return k*(e-b+1); return DIV(SUB(POW(k, e+1), POW(k,b)), k-1); } -LL Cpascal(LL n, LL k) -{ - vector< vector > c(n+1, vector(k+1)); - for(LL nn=1; nn<=n; ++nn) - for(LL kk=0; kk<=min(nn,k); ++kk) - c[nn][kk] = kk==0 || kk==nn ? 1 : ADD(c[nn-1][kk-1], c[nn-1][kk]); - return c[n][k]; -} - -vector< vector > MATMUL(vector< vector >& a, vector< vector >& b) -{ - int N = a.size(); - vector< vector > c(N, vector(N)); - for(int i=0; i > v(2, vector(2)); vector< vector > x(2, vector(2));