D - Redistribution
解法
・であるから、数え上げる数列の最大の長さはを超えない.
・また、ある項を使うとすると、までの長さが求まっていれば良い.
・動的計画法.
1.をなめながらの全状態を更新していくver
2.ある状態からを使う推移を考えるver
後者のほうが好きです
・時間計算量は
スマートな方法
式変形を考えると計算量が改善できるらしい.すごい.
以下では、下のコードから計算量の改善を考えてみる.
はからの推移で求まることがわかる.
したがって、
これより
が導ける.つまり、シグマが消えて計算量が改善できる.
までのすべてのを用いて更新する必要はなく、直前のやつだけを使うと十分であることがわかる.
改善したやつ
#include<bits/stdc++.h> using namespace std; using Int = long long; constexpr Int mod = 1e9 + 7; int main(){ Int S; cin >> S; vector<Int>dp(S+1,0LL); dp[0] = 1; for(int s = 0; s <= S; ++s){ for(int i = 3; i <= S; ++i){ if(dp[s] == 0)continue; if(s + i <= S) dp[i + s] += dp[s], dp[i + s] %= mod; } } cout << dp[S] << endl; }
参考
けんちょんさんの記事を参考にしました。感謝です。
drken1215.hatenablog.com