1004

思路:
本意是求将a切成几块后,每块之和是p的倍数的最大块数。容易联想到“给定一串数字和一些乘号,用乘号分割数字所得的最大值”这个DP问题。穷举所有分割。

不知道为什么,编译错误的太多了。

通过代码:

#include<iostream>
#include<vector>
#include<algorithm>

const int MAXN = 1e5 + 5;
using namespace std;
int T, n, p, a[MAXN], sum[MAXN], last[MAXN], dp[MAXN];

int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> T;
while (T--)
{
cin >> n >> p;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
memset(last, -1, sizeof(last));
dp[0] = 0;
last[0] = 0;
for (int i = 1; i <= n; i++)
{
sum[i] = (sum[i - 1] + a[i]) % p;
dp[i] = dp[i - 1];
if (last[sum[i]] != -1) dp[i] = max(dp[i], dp[last[sum[i]]] + 1);
last[sum[i]] = i;
}
cout << dp[n] << '\n';
}
return 0;
}

 

1009

思路:

先从左到右遍历字符串一遍,看是否有解;若有解,将‘*’通过cnt的计数转化为两种括号;最后通过二分查找找到最短的字符串。

通过代码:

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

const int MAXN = 1e5 + 5;
int T;

int main()
{
cin >> T;
while(T--)
{
string S, out;
cin >> S;
int left = 0, right = 0, cnt[3] = {};
for (int i = 0; i < S.length() && right >= 0; ++i)
{//一来一回
if (S[i] == '(')
{
++left;
++cnt[0];
}
else
{
--left;
if (left < 0)
left = 0;
}
if (S[i] == ')')
{
--right;
++cnt[1];
}
else
{
++right;
}
}

//转换‘*’
for (int i = 0; i < S.length() && cnt[0] < cnt[1]; ++i)
{
if (S[i] == '*')
{
S[i] = '(';
++cnt[0];
}
}
for (int i = S.length() - 1; i >= 0 && cnt[0] > cnt[1]; --i)
{
if (S[i] == '*')
{
S[i] = ')';
++cnt[1];
}
}

int cLeft = 0, cRight = (S.length() - cnt[0] - cnt[1]) / 2;
while (cLeft < cRight)
{//二分查找
int cMid = (cLeft + cRight) / 2;
out.append(S);
for (int i = S.length() - 1, suf = cMid; i >= 0 && suf > 0; --i)
{
if (out[i] == '*')
{
out[i] = ')';
--suf;
}
}
int sgn = 0;
for (int i = 0, pre = cMid; i < S.length() && sgn >= 0; ++i)
{
if (out[i] == '(')
{
++sgn;
}
else if (out[i] == ')')
{
--sgn;
}
else if (pre > 0)
{
--pre;
++sgn;
}
}
if (!sgn)
{
cRight = cMid;
}
else
{
cLeft = cMid + 1;
}
}

for (int i = S.length() - 1, suf = cLeft; i >= 0 && suf > 0; --i)
if (S[i] == '*')
{
S[i] = ')';
--suf;
}
int m = 0;
for (int i = 0, pre = cLeft; i < S.length(); ++i)
{
if (S[i] != '*')
{

out[m++] = S[i];
}
else if (pre > 0)
{
out[m++] = '(';
--pre;
}
}
out[m] = '\0';

if (right < 0 || left > 0)
{
cout << "No solution!\n";
}
cout << out << '\n';
}
return 0;
}