結果

問題 No.616 へんなソート
ユーザー startcppstartcpp
提出日時 2017-12-29 20:12:36
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 35 ms / 2,000 ms
コード長 1,861 bytes
コンパイル時間 420 ms
コンパイル使用メモリ 54,976 KB
実行使用メモリ 29,408 KB
最終ジャッジ日時 2024-06-01 06:41:19
合計ジャッジ時間 1,492 ms
ジャッジサーバーID
(参考情報)
judge1 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,940 KB
testcase_03 AC 2 ms
6,944 KB
testcase_04 AC 2 ms
6,944 KB
testcase_05 AC 2 ms
6,944 KB
testcase_06 AC 2 ms
6,944 KB
testcase_07 AC 2 ms
6,940 KB
testcase_08 AC 2 ms
6,940 KB
testcase_09 AC 2 ms
6,944 KB
testcase_10 AC 1 ms
6,944 KB
testcase_11 AC 2 ms
6,940 KB
testcase_12 AC 3 ms
6,940 KB
testcase_13 AC 22 ms
16,980 KB
testcase_14 AC 2 ms
6,940 KB
testcase_15 AC 2 ms
6,948 KB
testcase_16 AC 2 ms
6,944 KB
testcase_17 AC 20 ms
17,612 KB
testcase_18 AC 10 ms
7,296 KB
testcase_19 AC 9 ms
6,944 KB
testcase_20 AC 2 ms
6,944 KB
testcase_21 AC 2 ms
6,940 KB
testcase_22 AC 5 ms
6,944 KB
testcase_23 AC 1 ms
6,944 KB
testcase_24 AC 1 ms
6,940 KB
testcase_25 AC 2 ms
6,944 KB
testcase_26 AC 4 ms
6,944 KB
testcase_27 AC 4 ms
6,940 KB
testcase_28 AC 35 ms
29,408 KB
testcase_29 AC 34 ms
28,892 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

//1,2,3,…の順で挿入して順列を作る。このときの樹形図を書いて、反転数の増加量を枝に記入してみる。
//すると、合計がK以下になるように「{0},{0,1},{0,1,2},…,{0,1,…,N-1}の中からそれぞれ1要素ずつ選ぶ」方法の数、が答えになると分かる。
//選んでいく過程で使用する情報は、「今いくつめの{}から選んでいるか?, 今までの和」の2つなので、この2つをキーにして漸化式が立ちそうだと分かる。
//dp[i][j] = {0},{0,1},…,{0,1,…,i}の中からそれぞれ1要素ずつ選んで、選んだ要素の合計をjにする方法の数
//とおくと、dp[0][0] = 1として、以下の漸化式を(i, j)昇順に回せばよいことが分かる。(個人的には、DAGの経路数をイメージすると分かりやすいです。)
//dp[i + 1][j + [0,1,…,i+1]] += dp[i][j]
//適宜余りを取りつつ更新すると、O(N^4)またはO(N^3K)で間に合わない。ここで、更新が「区間加算」になっていることに注目して、各iについてimos法で更新すると
//O(N^3)またはO(N^2 K)で間に合う。
#include <iostream>
using namespace std;

int mod = 1000000007;
int n, K;
int dp[300][50000];

int main() {
	int i, j;
	
	cin >> n >> K;
	
	dp[0][0] = 1;
	for (i = 0; i < n - 1; i++) {
		for (j = 0; j <= i * (i + 1) / 2; j++) {
			dp[i + 1][j] += dp[i][j];
			if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
			dp[i + 1][j + i + 2] += mod - dp[i][j];
			if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
		}
		for (j = 1; j <= (i + 1) * (i + 2) / 2; j++) {
			dp[i + 1][j] += dp[i + 1][j - 1];
			if (dp[i + 1][j] >= mod) dp[i + 1][j] -= mod;
		}
	}
	
	int ans = 0;
	for (j = 0; j <= K; j++) {
		ans += dp[n - 1][j];
		if (ans >= mod) ans -= mod;
	}
	cout << ans << endl;
	return 0;
}
0