kmjp's blog

競技プログラミング参加記です

yukicoder : No.3403 Count 1210 Sequence

これは割とすんなりだった。
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;
		
	}
}

まとめ

割とシンプルな解法で済んだ。