ABC135
B
暴力枚举交换
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
int cnt = 0;
int flag = 0;
for (int k = 1; k <= n - 1; k++)
{
if (a[k] >= a[k + 1])
flag = 1;
}
if (!flag)
{
cout << "YES" << endl;
return 0;
}
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
memcpy(b, a, sizeof a);
int flag = 0;
swap(b[i], b[j]);
for (int k = 1; k <= n - 1; k++)
{
if (b[k] >= b[k + 1])
flag = 1;
}
if (!flag)
{
cout << "YES" << endl;
return 0;
}
}
}
cout << "NO" << endl;
C
贪心,尽量取 (i) 位置的值,而不取 (i + 1) 位置的值。注意 (ll)
LL n;
cin >> n;
rep(i, n + 1) cin >> a[i];
rep(i,n) cin >> b[i];
LL ans = 0;
rep(i,n + 1)
{
LL cnt = a[i] + a[i + 1];
if(cnt >= b[i])
{
if(b[i] >= a[i])
{
LL _ = b[i] - a[i];
a[i] = 0;
a[i + 1] -= _;
ans += b[i];
}
else
{
a[i] -= b[i];
ans += b[i];
}
}
else
{
ans += cnt;
b[i] -= cnt;
a[i] = 0;
a[i + 1] = 0;
}
}
cout << ans << endl;
D
dp
中的 sum
问题:
余数 给的很小,那么可以通过余数做做文章。
dp[i][j]表示到第 i 位时余数为 j 这样的数的个数
起始值:dp[0][0] = 0
答案:dp[n][5]
s[i] == 数字
: dp[i][(j * 10 + s[i] - '0') % 13] = (dp[i][(j * 10 + s[i] - '0') % 13] + dp[i - 1][j])%mod;
(j * 10 + s[i] -'0') % 13是由 j 变换过来的,最后答案要加上 dp[i - 1][j]
s[i] == ?
: 枚举 (0 sim 9) 考虑 (i) 位置依次放置 (0 sim 9) ,
dp[i][(j * 10 + k) % 13] = (dp[i][(j * 10 + k) % 13] + dp[i - 1][j]) % mod;
余数为 (j * 10 + k) % 13是由 j 变换过来的,所以最后的答案中要加上 dp[i - 1][j]的值
余数变换是不变的,如 27 % 13 == 1,(27 * 10) % 13 == 10 == 1 * 10
那么就可以直接乘上 (i - 1) 位置的余数 + 当前 (i) 位置的值再取余数是不变的。
LL dp[N][100];
char s[N];
int main()
{
scanf("%s", s + 1);
dp[0][0] = 1;
int n = strlen(s + 1);
for (int i = 1;i <= n;i++)
{
if (s[i] >= '0' && s[i] <= '9')
{
for (int j = 0; j < 13; j++)
{
dp[i][(j * 10 + s[i] - '0') % 13] = (dp[i][(j * 10 + s[i] - '0') % 13] + dp[i - 1][j])%mod;
}
}
else
{
for (int j = 0; j < 13;j++)
{
for (int k = 0; k <= 9;k++)
{
dp[i][(j * 10 + k) % 13] = (dp[i][(j * 10 + k) % 13] + dp[i - 1][j]) % mod;
}
}
}
}
cout << dp[n][5] << endl;
return 0;
}