提出 #36904203


ソースコード 拡げる

Copy
Copy
  1. #include <stdio.h>
  2.  
  3. #define MAX 3156
  4.  
  5. int N, P;
  6.  
  7. /* a + b mod P を返す */
  8. int add(int a, int b) {
  9. int ret = a + b;
  10. /* [0, P) の数を2個足した結果は 2*P 未満 */
  11. if (ret >= P) ret -= P;
  12. return ret;
  13. }
  14.  
  15. /* a - b mod P を返す */
  16. int sub(int a, int b) {
  17. if (b == 0) return a;
  18. /* b が正のとき、P - b は P 未満 */
  19. /* b が P 未満 のとき、P - b は正 */
  20. return add(a, P - b);
  21. }
  22.  
  23. /* a * b mod P を返す */
  24. int mul(int a, int b) {
  25. return (int)((long long)a * b % P);
  26. }
  27.  
  28. /* 同じ文字が len 文字連続した文字列に対して操作を行ったとき、何文字になるかを求める */
  29. int elementLength(int len) {
  30. int ans = 1; /* 最初にアルファベットを1個おく */
  31. /* 文字数の十進表現の長さを求める */
  32. do {
  33. ans++;
  34. len /= 10;
  35. } while (len > 0);
  36. return ans;
  37. }
  38.  
  39. /* [もとの文字列を何文字決めたか][操作後の文字列が何文字になったか] */
  40. int memo[MAX][MAX];
  41. /* もとの文字列の長さの降順の累積和 */
  42. int memoSum[MAX][MAX];
  43.  
  44. int main(void) {
  45. int srcLen, destLen;
  46. if (scanf("%d%d", &N, &P) != 2) return 1;
  47.  
  48. /* 操作後の文字列が N 文字未満で、操作前の文字列が N 文字に到達した */
  49. for (destLen = 0; destLen < N; destLen++) {
  50. memo[N][destLen] = 1;
  51. memoSum[N][destLen] = 1;
  52. }
  53. /* 操作前の文字列の長い順に求めていく */
  54. for (srcLen = N - 1; srcLen >= 0; srcLen--) {
  55. /* 操作後の文字列が N 文字以上になったら条件を満たさないので、そこまで求めればいい */
  56. for (destLen = 0; destLen < N; destLen++) {
  57. int ans = 0;
  58. int i;
  59. int delta = 2; /* 操作後の文字列の長さが増える量 */
  60. int deltaLast = 9; /* 増える量が delta となる最後の置く長さ */
  61. /* 次に同じ文字を何文字置くか、それぞれを試す */
  62. for (i = 1; srcLen + i <= N; ) {
  63. /* 操作前の文字列が N 文字になるまでで打ち切る */
  64. if (srcLen + deltaLast > N) deltaLast = N - srcLen;
  65. /* 累積和を用いて加算する */
  66. ans = add(ans, sub(memoSum[srcLen + i][destLen + delta],
  67. memoSum[srcLen + deltaLast + 1][destLen + delta]));
  68. /* 次の部分について求める準備をする */
  69. i= deltaLast + 1;
  70. delta++;
  71. deltaLast = deltaLast * 10 + 9;
  72. }
  73.  
  74. if (srcLen == 0) {
  75. /* 最初は、好きな文字を選べる */
  76. ans = mul(ans, 26);
  77. } else {
  78. /* 前回使った文字以外の中から好きな文字を選べる */
  79. ans = mul(ans, 25);
  80. }
  81.  
  82. /* 結果をメモする */
  83. memo[srcLen][destLen] = ans;
  84. /* 累積和をとる */
  85. memoSum[srcLen][destLen] = add(memo[srcLen][destLen], memoSum[srcLen + 1][destLen]);
  86. }
  87. }
  88.  
  89. printf("%d\n", memo[0][0]);
  90. return 0;
  91. }
#include <stdio.h>

#define MAX 3156

int N, P;

/* a + b mod P を返す */
int add(int a, int b) {
	int ret = a + b;
	/* [0, P) の数を2個足した結果は 2*P 未満 */
	if (ret >= P) ret -= P;
	return ret;
}

/* a - b mod P を返す */
int sub(int a, int b) {
	if (b == 0) return a;
	/* b が正のとき、P - b は P 未満 */
	/* b が P 未満 のとき、P - b は正 */
	return add(a, P - b);
}

/* a * b mod P を返す */
int mul(int a, int b) {
	return (int)((long long)a * b % P);
}

/* 同じ文字が len 文字連続した文字列に対して操作を行ったとき、何文字になるかを求める */
int elementLength(int len) {
	int ans = 1; /* 最初にアルファベットを1個おく */
	/* 文字数の十進表現の長さを求める */
	do {
		ans++;
		len /= 10;
	} while (len > 0);
	return ans;
}

/* [もとの文字列を何文字決めたか][操作後の文字列が何文字になったか] */
int memo[MAX][MAX];
/* もとの文字列の長さの降順の累積和 */
int memoSum[MAX][MAX];

int main(void) {
	int srcLen, destLen;
	if (scanf("%d%d", &N, &P) != 2) return 1;

	/* 操作後の文字列が N 文字未満で、操作前の文字列が N 文字に到達した */
	for (destLen = 0; destLen < N; destLen++) {
		memo[N][destLen] = 1;
		memoSum[N][destLen] = 1;
	}
	/* 操作前の文字列の長い順に求めていく */
	for (srcLen = N - 1; srcLen >= 0; srcLen--) {
		/* 操作後の文字列が N 文字以上になったら条件を満たさないので、そこまで求めればいい */
		for (destLen = 0; destLen < N; destLen++) {
			int ans = 0;
			int i;
			int delta = 2; /* 操作後の文字列の長さが増える量 */
			int deltaLast = 9; /* 増える量が delta となる最後の置く長さ */
			/* 次に同じ文字を何文字置くか、それぞれを試す */
			for (i = 1; srcLen + i <= N; ) {
				/* 操作前の文字列が N 文字になるまでで打ち切る */
				if (srcLen + deltaLast > N) deltaLast = N - srcLen;
				/* 累積和を用いて加算する */
				ans = add(ans, sub(memoSum[srcLen + i][destLen + delta],
					memoSum[srcLen + deltaLast + 1][destLen + delta]));
				/* 次の部分について求める準備をする */
				i= deltaLast + 1;
				delta++;
				deltaLast = deltaLast * 10 + 9;
			}

			if (srcLen == 0) {
				/* 最初は、好きな文字を選べる */
				ans = mul(ans, 26);
			} else {
				/* 前回使った文字以外の中から好きな文字を選べる */
				ans = mul(ans, 25);
			}

			/* 結果をメモする */
			memo[srcLen][destLen] = ans;
			/* 累積和をとる */
			memoSum[srcLen][destLen] = add(memo[srcLen][destLen], memoSum[srcLen + 1][destLen]);
		}
	}

	printf("%d\n", memo[0][0]);
	return 0;
}

提出情報

提出日時
問題 E - RLE
ユーザ mikecat
言語 C (GCC 9.2.1)
得点 500
コード長 2849 Byte
結果 AC
実行時間 228 ms
メモリ 75728 KB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 500 / 500
結果
AC × 4
AC × 31
セット名 テストケース
Sample example_00.txt, example_01.txt, example_02.txt, example_03.txt
All example_00.txt, example_01.txt, example_02.txt, example_03.txt, test_00.txt, test_01.txt, test_02.txt, test_03.txt, test_04.txt, test_05.txt, test_06.txt, test_07.txt, test_08.txt, test_09.txt, test_10.txt, test_11.txt, test_12.txt, test_13.txt, test_14.txt, test_15.txt, test_16.txt, test_17.txt, test_18.txt, test_19.txt, test_20.txt, test_21.txt, test_22.txt, test_23.txt, test_24.txt, test_25.txt, test_26.txt
ケース名 結果 実行時間 メモリ
example_00.txt AC 2 ms 1660 KB
example_01.txt AC 1 ms 1748 KB
example_02.txt AC 1 ms 1700 KB
example_03.txt AC 228 ms 75728 KB
test_00.txt AC 54 ms 23916 KB
test_01.txt AC 4 ms 3712 KB
test_02.txt AC 72 ms 33028 KB
test_03.txt AC 48 ms 23060 KB
test_04.txt AC 1 ms 1972 KB
test_05.txt AC 16 ms 8752 KB
test_06.txt AC 64 ms 30516 KB
test_07.txt AC 72 ms 32768 KB
test_08.txt AC 25 ms 14768 KB
test_09.txt AC 145 ms 59592 KB
test_10.txt AC 224 ms 75552 KB
test_11.txt AC 46 ms 22828 KB
test_12.txt AC 40 ms 20712 KB
test_13.txt AC 83 ms 39056 KB
test_14.txt AC 87 ms 39772 KB
test_15.txt AC 2 ms 3000 KB
test_16.txt AC 10 ms 6636 KB
test_17.txt AC 50 ms 24856 KB
test_18.txt AC 79 ms 36644 KB
test_19.txt AC 209 ms 72716 KB
test_20.txt AC 224 ms 75716 KB
test_21.txt AC 227 ms 75628 KB
test_22.txt AC 224 ms 75648 KB
test_23.txt AC 215 ms 74216 KB
test_24.txt AC 217 ms 74364 KB
test_25.txt AC 224 ms 75272 KB
test_26.txt AC 1 ms 1668 KB


2022-11-30 (水)
22:07:03 +00:00