QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#853177 | #9922. Mah-jong | ruoye123456 | TL | 5ms | 4384kb | C++23 | 3.3kb | 2025-01-11 16:03:41 | 2025-01-11 16:03:50 |
Judging History
answer
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define N 100005
#define MOD 998244353
using namespace std;
int c[9];
int b[9];
int w[9] = {0, 1, 3, 15, 105, 735, 5145, 36015, 180075};
bitset<550000> ok;
vector<int> prefix[9]; // 存储每个数字的出现位置
unordered_map<int, bool> state_cache; // 缓存常见状态组合
// 使用位运算优化状态转移
inline int get_state(int t1, int t2, int t3, int t4, int t5, int t6, int t7, int t8) {
int idx = 0;
idx += w[1]*t1 + w[2]*t2 + w[3]*t3 + w[4]*t4;
idx += w[5]*t5 + w[6]*t6 + w[7]*t7 + w[8]*t8;
return idx;
}
void check() {
memcpy(b, c, sizeof(b));
for(int i=1; i<=6; ++i) {
if(b[i] < 0) return;
b[i] %= 3;
b[i+1] -= b[i];
b[i+2] -= b[i];
b[i] = 0;
}
if(b[7]>=0 && b[8]>=0 && b[7]%3==0 && b[8]%3==0) {
int idx = get_state(c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8]);
ok[idx] = 1;
state_cache[idx] = true;
}
}
void init() {
for(c[1]=0; c[1]<=2; ++c[1])
for(c[2]=0; c[2]<=4; ++c[2])
for(c[3]=0; c[3]<=6; ++c[3])
for(c[4]=0; c[4]<=6; ++c[4])
for(c[5]=0; c[5]<=6; ++c[5])
for(c[6]=0; c[6]<=6; ++c[6])
for(c[7]=0; c[7]<=4; ++c[7])
for(c[8]=0; c[8]<=2; ++c[8])
check();
}
inline int get_count(const vector<int>& pos, int l, int r) {
return upper_bound(pos.begin(), pos.end(), r) -
lower_bound(pos.begin(), pos.end(), l);
}
void solve() {
int n;
cin >> n;
// 清空前缀数组
for(int i = 1; i <= 8; i++) {
prefix[i].clear();
}
// 读入数据并构建前缀数组
vector<int> a(n + 1);
for(int i = 1; i <= n; i++) {
cin >> a[i];
prefix[a[i]].push_back(i);
}
int ans = 0;
// 枚举所有可能的长度为3的倍数的区间
for(int len = 3; len <= n; len += 3) {
for(int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
// 使用二分查找计算区间内每个数字的出现次数
vector<int> cnt(9);
for(int k = 1; k <= 8; k++) {
cnt[k] = get_count(prefix[k], i, j);
}
// 处理每个计数,应用相同的模运算规则
int t1 = cnt[1]; if(t1>=3) t1%=3;
int t2 = cnt[2]; if(t2>=5) t2=(t2-2)%3+2;
int t3 = cnt[3]; if(t3>=7) t3=(t3-4)%3+4;
int t4 = cnt[4]; if(t4>=7) t4=(t4-4)%3+4;
int t5 = cnt[5]; if(t5>=7) t5=(t5-4)%3+4;
int t6 = cnt[6]; if(t6>=7) t6=(t6-4)%3+4;
int t7 = cnt[7]; if(t7>=5) t7=(t7-2)%3+2;
int t8 = cnt[8]; if(t8>=3) t8%=3;
// 计算状态并查找是否合法
int state = get_state(t1, t2, t3, t4, t5, t6, t7, t8);
ans += ok[state];
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
// 预处理所有可能的状态
init();
while(T--) {
solve();
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 5ms
memory: 4384kb
input:
5 4 1 1 1 1 6 1 2 3 1 2 3 7 6 5 8 7 6 3 2 8 1 2 1 2 1 2 1 3 9 2 2 4 4 1 1 1 3 3
output:
2 5 1 3 2
result:
ok 5 number(s): "2 5 1 3 2"
Test #2:
score: -100
Time Limit Exceeded
input:
100 992 8 1 8 1 2 3 6 6 1 3 1 8 7 7 4 7 7 1 6 6 4 8 3 7 3 5 1 4 4 7 5 7 5 7 4 3 7 5 2 8 7 1 6 3 6 2 4 3 2 3 1 6 3 1 3 2 6 6 7 4 6 1 1 4 6 4 7 7 8 5 6 4 1 5 4 8 2 4 4 2 1 3 5 7 6 8 3 7 6 6 5 6 4 2 5 4 3 7 3 5 5 3 3 2 7 8 2 7 2 4 4 3 4 1 1 3 5 5 4 6 3 3 3 2 6 1 2 6 4 8 8 6 6 8 7 3 1 1 8 8 7 2 5 6 3 5 ...