1001:MG loves gold
直接用set或者map记录一下即可:
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int T, n, x;
cin >> T;
while(T--) {
cin >> n;
set<int> s;
int ans = 0;
for(int i = 0; i < n; ++i) {
cin >> x;
if(s.find(x) != s.end()) {
ans++;
s.clear();
s.insert(x);
} else {
s.insert(x);
}
}
cout << ans+1 << endl;
}
return 0;
}
这个题真的是很。。。。。,我们先看看题解怎么说:
这题更多算是想法题,有脑洞的同学可以各种乱搞。将问题转化成:求去掉K位数字后,不含前导零,且数字和是否能被三整除。按照预测,这里应该会汇聚本场最多的hack点。
我们设S0、S1、S2分别为原串上mod3=0、1、2数字的个数。 我们假定删除取模后为0、1、2的数字各A、B、C个,则显然有0<=A<=S0,0<=B<=S1,0<=C<=S2且K=A+B+C且Sum mod3=(A∗0+B∗1+C∗2)mod3=(S0∗0+S1∗1+S2∗2)mod3=bias。 枚举C的值,我们可得Bmod3=(bias−C∗2)mod3,A=K−B−C。如果有若干组A,B不逾界,可知这些(A,B,C)是在模意义下合法的解,但不一定满足没有前导零。
所以,对于【大于0的数】我们贪心地从后往前删除,对于0我们贪心地从前往后删除。
需要统计出:a3=第一个【mod3=0且非0的数】前0的个数(如果mod3=0且非0的数不存在,那么a3就取所有零的个数),E1=【第一个0前是否存在mod3=1的数】,E2=【第一个0前是否存在mod3=2的数】。
则以下情况满足任一种都能保证无前导零:A>=a3。B<S1且E1。C<S2且E2。
其实题解少考虑了一种情况,比如n = 5, k = 4
10010
只按照题解的做法答案是no,但其实是yes,这时我们只留下一个0,所以在题解的基础上加一组特判即可,WA了无数,愣是把C++写成了Java
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int T, n, k;
string numStr;
cin >> T;
while(T--) {
int modThreeEqualOne = 0, modThreeEqualTwo = 0, modThreeEqualZero = 0;
int takeModThreeEqualOne = 0, takeModThreeEqualTwo = 0, takeModThreeEqualZero = 0;
bool isModThreeEqualOneBeforeFirstZero = false, isModThreeEqualTwoBeforeFirstZero = false;
cin >> n >> k;
cin >> numStr;
int sum = 0;
for(int i = 0; numStr[i]; ++i) {
sum += (numStr[i] - '0');
switch((numStr[i]-'0') % 3) {
case 0: modThreeEqualZero++;
break;
case 1: modThreeEqualOne++;
break;
case 2: modThreeEqualTwo++;
break;
}
}
bool isFirstZero = false;
for(int i = 0; numStr[i]; ++i) {
if(numStr[i] == '0') {
isFirstZero = true;
}
if(!isFirstZero && (numStr[i]-'0') % 3 == 1) {
isModThreeEqualOneBeforeFirstZero = true;
}
if(!isFirstZero && (numStr[i]-'0') % 3 == 2) {
isModThreeEqualTwoBeforeFirstZero = true;
}
}
int tmpNum = 0;
for(int i = 0; numStr[i]; ++i) {
if(numStr[i] == '0') {
tmpNum++;
}
if(numStr[i] != '0' && (numStr[i] - '0') % 3 == 0)break;
}
bool isValidSol = false;
if(modThreeEqualZero && k == n-1) {
cout << "yes" << endl;
continue;
}
for(takeModThreeEqualTwo = 0; takeModThreeEqualTwo <= min(k, modThreeEqualTwo); ++takeModThreeEqualTwo) {
for(takeModThreeEqualOne = ((sum - takeModThreeEqualTwo*2) % 3 + 3) % 3; takeModThreeEqualOne <= min(k-takeModThreeEqualTwo, modThreeEqualOne); takeModThreeEqualOne += 3) {
takeModThreeEqualZero = k - takeModThreeEqualOne - takeModThreeEqualTwo;
if(takeModThreeEqualZero > modThreeEqualZero) continue;
if((takeModThreeEqualZero >= tmpNum) || (isModThreeEqualOneBeforeFirstZero && takeModThreeEqualOne < modThreeEqualOne)
|| (isModThreeEqualTwoBeforeFirstZero && takeModThreeEqualTwo < modThreeEqualTwo)) {
isValidSol = true;
break;
}
}
if(isValidSol) break;
}
if(isValidSol) {
cout << "yes" << endl;
}
else {
cout << "no" << endl;
}
}
return 0;
}