topcoder srm 669 level 3
给定整数X(X>=1 && X <= 10^18)和M,求将X分解为 a0*M^0 + a1*M^1 + ... + ai*M^i 形式的种类数目
很明显首先需要将X按M进制分解,问题关键是状态转移。
设 X = b0 * M^0 + b1*M^1 + ... + bn*M^n,bi = [0,M)。
对于bi*M^i,可以视作与其他分开考虑。所以问题的核心变成如何计算bi*M^i的拆解数目。
借鉴了别人的代码,有些状态矩阵的转移很微妙。
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a),__tzg_##i=(b);i<__tzg_##i;++i) #define urp(i,a,b) for(int i=(a),__tzg_##i=(b);i>=__tzg_##i;--i) #define rp(i,b) rep(i,0,b) #define repd(i,a,b) rep(i,a,(b)+1) #define mst(a,b) memset(a,b,sizeof(a)) #define vrp(it,v) for(auto it(v.begin());(it)!=(v.end());++it) #define vtr(v) (v).begin(),(v).end() #define mp(a,b) make_pair(a,b) #define fi first #define se second #define pb(a) push_back(a) #define _0(x) (!(x)) #define _1(x) (x) typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef long long ll; struct Matrix { typedef int T; const static int R = 70; const static int C = 70; const static T MOD = 1e9+7; T da[R][C]; int r, c; Matrix(const T _da[][C], int _r, int _c):r(_r),c(_c) {memcpy(da, _da, sizeof da);} Matrix(const Matrix & p):r(p.r),c(p.c) {memcpy(da, p.da, sizeof da);} Matrix(const int _r, const int _c, int _ty = 0):r(_r),c(_c) { memset(da, 0, sizeof da); if (_ty) for (int i = 0; i< r; ++i) da[i][i] = T(1); } Matrix operator * (const Matrix & a) const { Matrix res(r, a.c); for (int i = 0; i< res.r; ++i) for (int j = 0; j< res.c; ++j) for (int k = 0; k< c; ++k) { res.da[i][j] = ((long long)da[i][k] * a.da[k][j] + res.da[i][j])%MOD; } return res; } const T * operator [] (const int & i) const { return da[i]; } T * operator [] (int i) { return da[i]; } }; Matrix pow(const Matrix & a, int n){ Matrix res(a.r, a.c, 1), p = a; while (n) { if (n & 1) res = res*p; p = p*p; n >>= 1; } return res; } const static int MOD = 1e9+7; struct PowerPartition { int count(int M, long long X) { VI nums; while (X) { nums.pb(X % M); X /= M; } int log = nums.size(); vector<Matrix> pw; pw.pb(Matrix(1,1,1)); rep(i,1,log) { Matrix tmp = pow(pw.back(), M); tmp.r = tmp.c = i+1; repd(j,0,i) tmp[i][j] = 1; pw.pb(tmp); } Matrix cur(log,log,1); urp(i,log-1,0) { cur = cur*pow(pw[i], nums[i]); } int ans = 0; urp(i,log-1,0) { if ((ans += cur[i][0]) >= MOD) ans -= MOD; } return ans; } }; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif PowerPartition *p = new PowerPartition; assert(p->count( 893, 1000000000000000000ll) == 262776600); return 0; }