これは割とすんなりだった。
https://yukicoder.me/problems/no/3403
問題
以下のクエリが多数与えられるので、それぞれ答えよ。
整数N,Aが与えられる。
以下を満たす整数列は何通りか。
- 初項はA、末項が0
- 隣接要素の差の絶対値は等しい
解法
初項と末項を逆にして考える。
f(n,a) := 初項0、末項aの長さnの非負整数列で、隣接要素の差の絶対値が1のもの
とする。a>nの場合明らかにf(n,a)=0である。
あらかじめNの上限程度まで、前処理でf(n,a)のテーブルを埋めておこう。
N,Aに対し、Aの約数をdとすると、dを列挙しながらf(N,A/d)の和を取ればよい。
int T,N,A; ll dp[2525][2525]; const ll mo=998244353; vector<int> D[252525]; void solve() { int i,j,k,l,r,x,y; string s; for(i=1;i<=250000;i++) { for(j=i;j<=250000;j+=i) D[j].push_back(i); } dp[0][0]=1; FOR(i,2125) FOR(j,2125) { if(j) (dp[i+1][j-1]+=dp[i][j])%=mo; (dp[i+1][j+1]+=dp[i][j])%=mo; } cin>>T; while(T--) { cin>>N>>A; ll ret=0; FORR(d,D[A]) { if(A/d<=N-1) ret+=dp[N-1][A/d]; } cout<<ret%mo<<endl; } }
まとめ
割とシンプルな解法で済んだ。