結果
| 問題 | No.42 貯金箱の溜息 | 
| コンテスト | |
| ユーザー |  btk | 
| 提出日時 | 2015-05-21 16:39:20 | 
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 597 ms / 5,000 ms | 
| コード長 | 2,955 bytes | 
| コンパイル時間 | 637 ms | 
| コンパイル使用メモリ | 64,076 KB | 
| 実行使用メモリ | 5,376 KB | 
| 最終ジャッジ日時 | 2024-07-06 04:22:19 | 
| 合計ジャッジ時間 | 2,239 ms | 
| ジャッジサーバーID (参考情報) | judge2 / judge4 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| other | AC * 3 | 
ソースコード
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const LL MOD = (LL)1e9 + 9;
struct V{
	LL num[12];
	LL *f = num;
	LL *sub = num + 6;
	LL& operator[](int i){
		return num[i];
	}
	void operator=(V another){
		for (int i = 0; i < 12; i++){
			num[i] = another[i];
		}
	}
	V operator+(V &another){
		V res;
		for (int i = 0; i < 12; i++){
			res[i] = (num[i] + another[i])%MOD;
		}
		return res;
	}
	LL operator*(V &another){
		LL res=0;
		for (int i = 0; i < 12; i++){
			res += num[i] * another[i];
			res %= MOD;
		}
		return res;
	}
};
struct M{
	V row[15];
	V& operator[](int i){
		return row[i];
	}
	void operator=(M another){
		for (int i = 0; i < 12; i++)
			for (int j = 0; j < 12; j++){
				row[i][j] = another[i][j];
			}
	}
	M operator+(M &another){
		M res;
		for (int i = 0; i < 12; i++){
			res[i] = (row[i] + another[i]);
		}
		return res;
	}
	M operator*(M &another){
		M res;
		for (int i = 0; i < 12; i++){
			for (int j = 0; j < 12; j++){
				res[i][j] = 0;
				for (int k = 0; k < 12; k++){
					res[i][j] += row[i][k] * another[k][j];
				}
				res[i][j] %= MOD;
			}
		}
		return res;
	}
	V operator*(V &another){
		V res;
		for (int i = 0; i < 12; i++){
			res[i] = 0;
			for (int j = 0; j < 12; j++)	
				res[i] += row[i][j] * another[j];
			res[i] %= MOD;
		}
		return res;
	}
};
const LL YEN[] = { 1, 5, 10, 50, 100, 500 };
V dpf[6][501];
V dpsub[6][501];
LL ALL[6][501];
LL SUB[6][501];
#define LOGN 61
M m[LOGN];
void init(){
	for (int i = 0; i < 6; i++){
		dpf[i][0].f[i] = 1;
		dpsub[i][0].sub[i] = 1;
	}
	for (int i = 1; i <= 500; i++){
		dpf[0][i].f[0] = dpsub[0][i].sub[0] = 1;
	}
	for (int i = 1; i < 6; i++){
		for (LL j = YEN[i]; j <= 500; j+=YEN[i]){
			for (int k = 0; k < 6; k++){
				dpsub[i][j] = dpsub[i][j - YEN[i]] + dpf[i - 1][j - YEN[i]];
				dpf[i][j] = dpsub[i][j] + dpf[i-1][j];
			}
		}
	}
	for (int i = 0; i < 6; i++){
		m[0].row[i] = dpf[i][500];
		m[0].row[i + 6] = dpsub[i][500];
	}
	for (int i = 1; i < LOGN; i++){
		m[i] = m[i - 1] * m[i - 1];
	}
	for (int i = 0; i < 501; i++){
		SUB[0][i] = ALL[0][i] = 1;
	}
	for (int i = 1; i < 6; i++){
		for (LL j = YEN[i]; j <=500; j++){
			SUB[i][j] = (SUB[i][j - YEN[i]] + ALL[i - 1][j - YEN[i]]) % MOD;
		}
		for (LL j = 0; j <= 500; j++){
			ALL[i][j] = (SUB[i][j] + ALL[i - 1][j]) % MOD;
		}
	}
}
int main(){
	int T;
	LL n;
	cin >> T;
	init();
	while (T--){
		cin >> n;
		M matrix;
		
		for (int i = 0; i < 12; i++){
			for (int j = 0; j < 12; j++){
				matrix[i][j] = 0;
			}
			matrix[i][i] = 1;
		}
		
		V res;
		for (int i = 0; i < 6; i++){
			res[i] = ALL[i][n%500];
			res[i + 6] = SUB[i][n%500];
		}
		/*
		for (int i = 0; i < 6; i++){
			matrix.row[i] = dpf[i][n%500];
			matrix.row[i + 6] = dpsub[i][n%500];
		}
		*/
		n /= 500;
		for (int i = 0; i < LOGN; i++){
			if (n & 1)matrix = m[i]*matrix;
			n >>= 1;
		}
		res = matrix*res;
		cout << res[5] << endl;
	}
}
            
            
            
        