QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#283356#2576. 麻将yhk1001100 ✓1031ms17960kbC++143.8kb2023-12-14 15:24:392023-12-14 15:24:40

Judging History

This is the latest submission verdict.

  • [2023-12-14 15:24:40]
  • Judged
  • Verdict: 100
  • Time: 1031ms
  • Memory: 17960kb
  • [2023-12-14 15:24:39]
  • Submitted

answer

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
using namespace std;

const int N = 100, M = N << 2;
const int SZ = 2100;
const long long P = 998244353;

int n, m;
int cnt[N + 5];

struct Info
{
	int dp[3][3];//(i - 1, i), i

	Info()
	{
		memset(dp, -1, sizeof(dp));//illegal statement, unreachable
	}
	bool win()
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				if (dp[i][j] >= 4)
					return true;
		return false;
	}
	void add(int x)
	{
		int tmp[3][3];
		memset(tmp, -1, sizeof(tmp));

		for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
		{
			if (dp[i][j] == -1)
				continue;
			for (int shun = 0; shun <= x - i - j && shun < 3; shun++)//i, i + 1, i + 2
				tmp[j][shun] = max(tmp[j][shun], dp[i][j] + i + (x - i - j - shun) / 3);
		}
		for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			tmp[i][j] = min(tmp[i][j], 4);//to simplify automaton

		memcpy(dp, tmp, sizeof(dp));
		return ;
	}
	void tomax(const Info& info)
	{
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				dp[i][j] = max(dp[i][j], info.dp[i][j]);
		return ;
	}
};

struct State
{
	Info info[2];//que tou
	int pairs = 0;//7 pairs

	void add(int x)
	{
		info[1].add(x);
		if (x >= 2)
		{
			Info tmp = info[0];//should init tmp.pairs !
			tmp.add(x - 2);
			info[1].tomax(tmp);
		}
		info[0].add(x);

		pairs += (x >= 2);
		return ;
	}
	bool win()
	{
		return info[1].win() || pairs >= 7;
	}
	bool operator < (const State& state) const
	{
		for (int t = 0; t < 2; t++)
		for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			if (info[t].dp[i][j] != state.info[t].dp[i][j])
				return info[t].dp[i][j] < state.info[t].dp[i][j];
		return pairs < state.pairs;
	}
};

map<State, int> id;
int tot;
queue<State> q;

int g[SZ + 5][5];

void build()
{
	State st;
	st.info[0].dp[0][0] = 0;
	id[st] = ++tot;
	q.push(st);
	
	while (!q.empty())
	{
		State u = q.front();
		q.pop();
		int idu = id[u];

		for (int x = 0; x <= 4; x++)
		{
			State v = u;
			v.add(x);
			if (!v.win() && !id[v])//winner node: 0
			{
				id[v] = ++tot;
				q.push(v);
			}
			g[idu][x] = id[v];
		}
	}
	return ;
}

long long fac[M + 5], inv[M + 5];
long long ksm(long long d, long long u)
{
	long long res = 1;
	while (u)
	{
		if (u & 1)
			res = res * d % P;
		u >>= 1;
		d = d * d % P;
	}
	return res;
}
void initC()
{
	fac[0] = 1;
	for (int i = 1; i <= m; i++)
		fac[i] = fac[i - 1] * i % P;
	inv[m] = ksm(fac[m], P - 2);
	for (int i = m - 1; i >= 0; i--)
		inv[i] = inv[i + 1] * (i + 1) % P;
	return ;
}
long long C(int x, int y)
{
	if (x < y)
		return 0ll;
	return fac[x] * inv[y] % P * inv[x - y] % P;
}

long long dp[2][M + 5][SZ + 5];//i cards, at node u

int main()
{
	// freopen("mahjong.in", "r", stdin);
	// freopen("mahjong.out", "w", stdout);

	scanf("%d", &n);
	m = 4 * n;
	for (int i = 1, w, t; i <= 13; i++)
	{
		scanf("%d%d", &w, &t);
		cnt[w]++;
	}

	build();
	initC();

	int p = 0;
	dp[0][0][1] = 1;
	for (int num = 1; num <= n; num++)
	{
		for (int i = 0; i <= (num - 1) * 4; i++)//at most (num - 1) * 4 cards, run faster
		for (int u = 1; u <= tot; u++)
		{
			for (int to = cnt[num]; to <= 4 && i + to <= m; to++)
			{
				int v = g[u][to];
				dp[p ^ 1][i + to][v] = (dp[p ^ 1][i + to][v] + 
										dp[p][i][u] * C(4 - cnt[num], to - cnt[num]) % P) % P;
			}
		}

		memset(dp[p], 0, sizeof(dp[p]));
		p ^= 1;
	}

	long long ans = 1;//all situations need at least 1 card
	for (int i = 14; i <= m; i++)
	{
		long long sum = 0;
		for (int u = 1; u <= tot; u++)
			sum = (sum + dp[p][i][u]) % P;
		sum = sum * fac[i - 13] % P * fac[m - i] % P * inv[m - 13] % P;
		ans = (ans + sum) % P;
	}
	printf("%lld\n", ans);
	return 0;
}

详细

Test #1:

score: 10
Accepted
time: 5ms
memory: 17700kb

input:

5
1 1
1 2
1 3
1 4
2 1
3 1
3 2
3 3
3 4
5 1
5 2
5 3
5 4

output:

570425346

result:

ok single line: '570425346'

Test #2:

score: 10
Accepted
time: 7ms
memory: 17616kb

input:

5
1 3
2 4
4 3
5 3
3 1
5 4
4 2
1 4
4 4
3 3
3 2
1 1
2 2

output:

713031682

result:

ok single line: '713031682'

Test #3:

score: 10
Accepted
time: 26ms
memory: 17692kb

input:

13
1 3
12 1
12 2
1 4
13 3
13 2
3 2
13 1
1 1
3 4
3 3
1 2
12 3

output:

868236068

result:

ok single line: '868236068'

Test #4:

score: 10
Accepted
time: 21ms
memory: 17632kb

input:

13
1 1
13 1
2 3
1 3
3 1
3 4
2 1
13 4
1 4
12 2
13 3
12 3
3 2

output:

234399821

result:

ok single line: '234399821'

Test #5:

score: 10
Accepted
time: 22ms
memory: 17668kb

input:

13
2 3
2 1
12 2
13 2
2 2
1 2
13 3
12 4
13 4
3 4
3 1
12 3
1 3

output:

892522858

result:

ok single line: '892522858'

Test #6:

score: 10
Accepted
time: 695ms
memory: 17928kb

input:

81
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1

output:

152635587

result:

ok single line: '152635587'

Test #7:

score: 10
Accepted
time: 923ms
memory: 17616kb

input:

94
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1

output:

339459976

result:

ok single line: '339459976'

Test #8:

score: 10
Accepted
time: 963ms
memory: 17628kb

input:

96
1 2
1 3
1 4
1 1
2 2
2 3
2 4
2 1
3 2
3 3
3 4
3 1
4 2

output:

230028597

result:

ok single line: '230028597'

Test #9:

score: 10
Accepted
time: 722ms
memory: 17960kb

input:

83
1 2
1 3
1 4
1 1
2 2
2 3
2 4
2 1
3 2
3 3
3 4
3 1
4 2

output:

967250236

result:

ok single line: '967250236'

Test #10:

score: 10
Accepted
time: 1031ms
memory: 17676kb

input:

100
67 1
26 4
12 4
11 4
30 4
29 1
1 4
13 3
30 1
64 2
63 1
20 2
32 4

output:

345132636

result:

ok single line: '345132636'

Extra Test:

score: 0
Extra Test Passed