Skip to content

Commit

Permalink
Merge pull request #826 from maspypy/stirling
Browse files Browse the repository at this point in the history
Stirling Number (small p)
  • Loading branch information
yosupo06 authored Aug 8, 2022
2 parents ba51ef8 + 64e3d20 commit fb610aa
Show file tree
Hide file tree
Showing 26 changed files with 1,037 additions and 0 deletions.
62 changes: 62 additions & 0 deletions math/stirling_number_of_the_first_kind_small_p_large_n/checker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// https://github.com/MikeMirzayanov/testlib/blob/master/checkers/wcmp.cpp

// The MIT License (MIT)

// Copyright (c) 2015 Mike Mirzayanov

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "testlib.h"

using namespace std;

int main(int argc, char * argv[])
{
setName("compare sequences of tokens");
registerTestlibCmd(argc, argv);

int n = 0;
string j, p;

while (!ans.seekEof() && !ouf.seekEof())
{
n++;

ans.readWordTo(j);
ouf.readWordTo(p);

if (j != p)
quitf(_wa, "%d%s words differ - expected: '%s', found: '%s'", n, englishEnding(n).c_str(), compress(j).c_str(), compress(p).c_str());
}

if (ans.seekEof() && ouf.seekEof())
{
if (n == 1)
quitf(_ok, "\"%s\"", compress(j).c_str());
else
quitf(_ok, "%d tokens", n);
}
else
{
if (ans.seekEof())
quitf(_wa, "Participant output contains extra tokens");
else
quitf(_wa, "Unexpected EOF in the participants output");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
9 7
0 0
1 0
1 1
5 0
5 1
5 2
5 3
5 4
5 5
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
7 7
40 0
40 10
40 20
40 30
40 40
1000000007 998244353
1000000000000000000 1000000000000000000
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <iostream>

#include "../params.h"
#include "random.h"

bool is_prime(int p) {
if (p <= 1) return false;
for (int i = 2; i < p; ++i)
if (p % i == 0) return false;
return true;
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int T = T_MAX;
int p;
while (1) {
p = gen.uniform<int>(P_MIN, P_MAX);
if (is_prime(p)) break;
}
printf("%d %d\n", T, p);

for (int t = 0; t < T; ++t) {
long long n = gen.uniform<long long>(0, N_MAX);
long long k = gen.uniform<long long>(0, n);
printf("%lld %lld\n", n, k);
}
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <iostream>

#include "../params.h"
#include "random.h"

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int primes[] = {2, 3, 5, 7, 101, 4999};

int T = T_MAX;
int p = primes[seed % 6];
printf("%d %d\n", T, p);

int n_max = 5000;
for (int t = 0; t < T; ++t) {
long long n = gen.uniform<int>(0, n_max);
long long k = gen.uniform<int>(0, n);
printf("%lld %lld\n", n, k);
}
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <iostream>

#include "../params.h"
#include "random.h"

using namespace std;
using ll = long long;
bool is_prime(int p) {
if (p <= 1) return false;
for (int i = 2; i < p; ++i)
if (p % i == 0) return false;
return true;
}

// p が小さいケースは、答が 0 ばかりにならないように注意して作る
int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int primes[] = {2, 3, 5, 7, 11, 13};

int T = T_MAX;
int p = primes[seed % 6];
printf("%d %d\n", T, p);

auto nonzero_binom = [&]() -> pair<ll, ll> {
ll a = gen.uniform<ll>(0, N_MAX / p);
auto dfs = [&](auto& dfs, ll a) -> ll {
if (a <= p) return gen.uniform<ll>(0, a);
ll r = a % p;
a /= p;
ll b = dfs(dfs, a);
return p * b + (gen.uniform<ll>(0, r));
};
ll b = dfs(dfs, a);
return {a, b};
};

auto gen_nk = [&]() -> pair<ll, ll> {
while (1) {
auto [a, b] = nonzero_binom();
ll m = gen.uniform<ll>(0, p);
ll n = a * p + m;
ll k = p * b + (a - b) + gen.uniform<ll>(0, m);
if (0 <= k && k <= n && n <= N_MAX) return {n, k};
}
};

for (int t = 0; t < T; ++t) {
auto [n, k] = gen_nk();
printf("%lld %lld\n", n, k);
}
return 0;
}
42 changes: 42 additions & 0 deletions math/stirling_number_of_the_first_kind_small_p_large_n/hash.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"example_00.in": "c16f54d7f1281fb5f618a684053b512cf2cba71689396b4e1fb5a56cf11667ce",
"example_00.out": "21f95cb1af14205f145524442956ae96eabe6bfd2082388002d1247174d7b86e",
"example_01.in": "f0a91f062c908735a6c24a5ef90fd16bf45324e11aec4d283052f7e4ff0cbe42",
"example_01.out": "eed1a4b4a1d0b04c8ff891c2cb3aa69168063d3e0e46515241826ef040927a61",
"random_00.in": "1249d44ad552ed2ccab609641a194e7fd07b8e544222e8fa124ffe9fec8209b0",
"random_00.out": "51489d3975cf9f695e48f374334c80c498e62dfaaae2c8329b8ad73e293194f9",
"random_01.in": "1dc43972adae22056f0731f678b56ff3835630f01e5196a34bd844fd346edc3e",
"random_01.out": "aac767c4d9e2b94c536ac192396ebdc53b4230bc185faaf6cb8874097731e755",
"random_02.in": "f1d80f1bcab3b9a18fe95b57caa181bb20f65c8ea05a806559ac2249f370eaec",
"random_02.out": "4d298e3e75e3b746ca92195255b60834f79ed722503a551e333cc7648060cc8b",
"random_03.in": "7e369e909ede8bc8e09e2354a11d793cd3a394957d0b2fb9d68b7194a14ecae1",
"random_03.out": "112ff12de4e7e58fbac0e45ffb488473e2b8339e28e6cd0f6f9a2cec0c86eee4",
"random_04.in": "240fc7f8d572e270fc5a6a7dc97a132f67029f2a45892ed4ee071672f5d02560",
"random_04.out": "41ec82937b9155ed81c626a0ce08fdcd739cb3213cb429b77133a0ded5aa53b9",
"random_05.in": "1fc63785c8f706efd2527959ba233ba63e1b2bf6761ab2180e66b07d0319c519",
"random_05.out": "ec84aa3cc92b3c996d2230f55464f574a572c2e5ccce0fa6ddeb61a04ceb33af",
"small_n_00.in": "558d85596cbccb5ab52d78d1cef3ff802b414084c4a80594516da44c7d2bd70a",
"small_n_00.out": "002363e799a2a584fa2c94b3aa0d771ba13366edc016bb1b6ed667622cdeb5ec",
"small_n_01.in": "38c07365f1cd6720e3c6248e96eaadb24433116d1812ce83ac03e2d301b13efe",
"small_n_01.out": "70b9fac1ce6d3bb6fde73c11bf1656e3b5830360e20392b6ea7494c1fc818461",
"small_n_02.in": "d4714164c0d4e8508d103fbb8bdcd6ad8b82c140b102f8786cc5d1e609d888bb",
"small_n_02.out": "49c86d0dbd6c436e9c2702efaf7d32fc430cc6749601970949e6fb38eedfb028",
"small_n_03.in": "cb17551e532c85adceed45fdb28b58d453a31b339f5a195e8c06138e8cecebdd",
"small_n_03.out": "447a2eeaa0b106ba8c59f45f631209d61efa2156b779a00aff8704a9cf60227f",
"small_n_04.in": "7b779b58ff77e31cc74dd392c3fc55433c5750f96a373704cfa1df804efde947",
"small_n_04.out": "e1d6794c6575c6870ed2db1315b76661a9a365e3255b29d5fdabd676cfd6fe05",
"small_n_05.in": "8a9b0832a9f14d3eb3f42dfe85a1f3f655e4daca91a0826486e51076c051632f",
"small_n_05.out": "9c1a2b4a3ed6ba4469df5ce67d01c5baba7f4b2c528e62e3bf26df97b81bcd74",
"small_p_00.in": "ab99ea648c4580e59e630ee1a6334fda467bf0c57b2e3dbab8aea534a84eb5ef",
"small_p_00.out": "a7e6f4bf5a8f215badc2778583448218a72c388a339f726b7c72e507015288d9",
"small_p_01.in": "048439738fe7542dc7ac23383dd9e07b7972ed60f2c092632830048556efbea9",
"small_p_01.out": "e1d3dd7ba36411c0ac234dfcefe90d394db44a64448402d05dfc73fa6c5717cf",
"small_p_02.in": "09668c9bb5f5bf3ac56dfbaf6bb45a1456228166ef3989208b13e434f32bcdbd",
"small_p_02.out": "ea11acc2723773b8b4e045125039a14876994be6fa202d7862b1182eb6db2ffc",
"small_p_03.in": "e3d16b21a96874c33e33089da94888aa7f6472b10e8013a53a8032cd32b0767d",
"small_p_03.out": "1c59b8f5b1afc076784ea1656c17575731f0b9af14afe98412b772fa5cf3bf25",
"small_p_04.in": "4f3ef959eeec6e1990244de1ebacfbbb75fa05f47a2e5d131ed19a1aaabbcff4",
"small_p_04.out": "6358f7f1e653bb57b0e2f5da859baa58dddbc2e375db99ea93507a19f053740b",
"small_p_05.in": "547bce4b9c3d933c60c7767a34af4f97bd7b77f4a3db815e11215dd844be3c85",
"small_p_05.out": "7b71601410cb890439f38c1b246f473f59166ed66ebea84db98a57c062d4abe4"
}
29 changes: 29 additions & 0 deletions math/stirling_number_of_the_first_kind_small_p_large_n/info.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
title = 'Stirling Number of the First Kind (small p, large n)'
timelimit = 10.0
forum = "https://github.com/yosupo06/library-checker-problems/issues/817"

[[tests]]
name = "example.in"
number = 2
[[tests]]
name = "small_n.cpp"
number = 6
[[tests]]
name = "random.cpp"
number = 6
[[tests]]
name = "small_p.cpp"
number = 6


[[solutions]]
name = "naive.cpp"
wrong = false
allow_tle = true

[params]
T_MAX = 200_000
P_MIN = 2
P_MAX = 5000
N_MIN = 0
N_MAX = 1_000_000_000_000_000_000
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;

#include "stirling_number_query.hpp"

int main() {
int T, p;
scanf("%d %d\n", &T, &p);

Stirling_Number_Query X(p, 1, 0);

for (int t = 0; t < T; ++t) {
long long n, k;
scanf("%lld %lld\n", &n, &k);
int ans = X.S1(n, k);
printf("%d\n", ans);
}
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <vector>

const int LIM = 5010;

int S[LIM][LIM];

void gen_S(int p) {
S[0][0] = 1;
for (int i = 1; i < LIM; ++i) {
for (int j = 0; j < i + 1; ++j) {
int &x = S[i][j];
if (j) x += S[i - 1][j - 1];
x -= S[i - 1][j] * (i - 1);
x %= p;
if (x < 0) x += p;
}
}
}

void TLE() {
while (1) {}
}

int main() {
int T, p;
scanf("%d %d", &T, &p);

gen_S(p);

for (int t = 0; t < T; ++t) {
long long n, k;
scanf("%lld %lld", &n, &k);
if (n >= LIM) { TLE(); }
printf("%d\n", S[n][k]);
}
return 0;
}
Loading

0 comments on commit fb610aa

Please sign in to comment.