結果
問題 | No.41 貯金箱の溜息(EASY) |
ユーザー | codershifth |
提出日時 | 2015-07-27 00:47:07 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 25 ms / 5,000 ms |
コード長 | 4,808 bytes |
コンパイル時間 | 1,806 ms |
コンパイル使用メモリ | 163,120 KB |
実行使用メモリ | 6,940 KB |
最終ジャッジ日時 | 2024-07-16 00:21:32 |
合計ジャッジ時間 | 1,831 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 24 ms
6,812 KB |
testcase_01 | AC | 25 ms
6,940 KB |
ソースコード
#include <bits/stdc++.h> typedef long long ll; typedef unsigned long long ull; #define FOR(i,a,b) for(int (i)=(a);i<(b);i++) #define REP(i,n) FOR(i,0,n) #define RANGE(vec) (vec).begin(),(vec).end() using namespace std; class ModInt { long long value_; public: static long long Mod; static void set_mod(long long mod) { Mod= mod; } static long long get_mod(void) { return Mod; } ModInt() : value_(0) {} ModInt(long long val) { if (val >= Mod) value_ = val % Mod; else if (val >= 0) value_ = val; else // val < 0 value_ = (((-val)/Mod+1)*Mod+val) % Mod; assert(value_ < Mod); } ModInt(const ModInt &other) { value_ = other.value_; } ~ModInt() {} #define OPT(OP) \ ModInt operator OP (const ModInt &other) const { \ return ModInt(value_ OP other.value_); \ } \ template<class T> \ ModInt &operator OP##=(const T &other) { \ return (*this = (*this OP ModInt(other))); \ } OPT(+) OPT(-) OPT(*) #undef OPT bool operator==(const ModInt &other) const { return (value_ == other.value_); } bool operator!=(const ModInt &other) const { return !(*this == other); } ModInt &operator=(const ModInt &other) { value_ = other.value_; return *this; } // ModInt - int >= 0 みたいな比較は常に true になってしまうのでダメ (ModInt >= int は ok) // ModInt 間のみの比較にする bool operator<(const ModInt &other) const { return value_ < other.value_; } bool operator<=(const ModInt &other) const { return value_ <= other.value_; } bool operator>(const ModInt &other) const { return (other < *this); } bool operator>=(const ModInt &other) const { return (other <= *this); } // cast overload operator int() const { return value_; } operator long long() const { return value_; } static long long pow(ModInt a, int k) { ModInt b = 1; while (k > 0) { if (k & 1) b = (b*a); a = (a*a); k >>= 1; } return b; } // call when Mod is prime ModInt inv() { return ModInt::pow(*this, Mod-2); } long long value() const { return value_; } friend std::ostream& operator<<(std::ostream& os, const ModInt& m) { os<<m.value_; return os; } }; // 互換性サポートは int, long long のみ #define OPT(OP,T) \ ModInt operator OP (const ModInt &a, T b) { return a OP ModInt(b); } \ ModInt operator OP (T a, const ModInt &b) { return ModInt(a) OP b; } OPT(*,int) OPT(+,int) OPT(-,int) OPT(*,long long) OPT(+,long long) OPT(-,long long) #undef OPT long long ModInt::Mod = (long long)(1E+9)+9; class SighOfSavingsBoxEasy { public: void solve(void) { // Mk/111111LL <= 10^10/10^5 = 10^5 なので再帰でやると stackoveflow する。 // よって dp でやる必要がある。 // 111111LL 未満は 1 のコインで払う 1 通りしかないので // Mk/111111LL を 1~9 までのコインで払う払い方と考える ll MaxM = (ll)1E+10; MaxM = MaxM/111111LL; // dp[i] := i 円を 1~9 までのコインで払う払い方 vector<ModInt> dp(MaxM+1, 0); dp[0] = 1; // 111111LL 未満の払い方は 1 通り // O(10*MaxM) <= 10^6 for (int j = 1; j <= 9; ++j) for (ll i = 0; i < MaxM; ++i) { if (i+j <= MaxM) dp[i+j] += dp[i]; } // dp2[i] := i 円までを 1~9 のコインで払う払い方 // // これは j 円までを (j < i) 1~9 のコインではらって残りを // 本来の 1 円コインで払うという払い方ができるから累積 DP が必要 // vector<ModInt> dp2(MaxM+1, 0); dp2[0] = 1; for (ll i = 1; i <= MaxM; ++i) dp2[i] = dp2[i-1] + dp[i]; int T; cin>>T; REP(i,T) { ll m; cin>>m; cout<<dp2[m/111111LL]<<endl; } } }; #if 1 int main(int argc, char *argv[]) { ios::sync_with_stdio(false); auto obj = new SighOfSavingsBoxEasy(); obj->solve(); delete obj; return 0; } #endif