結果
| 問題 |
No.41 貯金箱の溜息(EASY)
|
| コンテスト | |
| ユーザー |
codershifth
|
| 提出日時 | 2015-07-27 00:47:07 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.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 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 2 |
ソースコード
#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
codershifth