2023.7.2牛客
2023.7.2 牛客
T1
很简单的模拟,需要注意前 \(3n\) 行都是前 \(n\) 个和后 \(n\) 个是 *,其他的都是 .,然后后 \(n\) 行的话,我们发现每一行两边多一个 .,也就是之前的 * 都往中间靠一列。
code:
#include <bits/stdc++.h>
#define int long long
#define N 1010
using namespace std;
int n;
char s[N][N];
signed main()
{
cin >> n;
int m = n * 4;
for(int i = 1; i <= m; i ++)
{
for(int j = 1; j <= m; j ++)
{
if(i <= m - n)
{
if(j > n && j <= m - n) s[i][j] = '.';
else s[i][j] = '*';
}
else
{
int o = i - 3 * n + 1;
if((j < o + n && j >= o) || (j <= m - o + 1 && j > m - o - n + 1)) s[i][j] = '*';
else s[i][j] = '.';
}
}
}
for(int i = 1; i <= m; i ++)
{
for(int j = 1; j <= m; j ++)
cout << s[i][j];
cout << endl;
}
return 0;
}
T2
我们首先发现值域有点大,需要离散化一下。
所以我们使用两个 map 存当前值为 \(x\) 颜色为蓝或红的数量来达到同样的效果。
我们首先都存起来,然后在输入颜色的时候,如果当前是蓝色就往答案里面加上当前值为红色的元素的个数,反之加入红色。
最后我们发现每一对统计了两遍,除以二即可。
#include <bits/stdc++.h>
#define int long long
#define N 2001000
using namespace std;
int n, a[N], ans;
char s[N];
map<int, int> mpa, mpb;
signed main()
{
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++)
{
cin >> s[i];
if(s[i] == 'B') mpb[a[i]] ++;
else mpa[a[i]] ++;
}
for(int i = 1; i <= n; i ++)
{
if(s[i] == 'B') ans += mpa[a[i]];
else ans += mpb[a[i]];
}
cout << ans / 2 << endl;
return 0;
}
T3
我们可以发现题目里说一定有解,而字符只有两种,所以 \(01\) 的数量相差最多为 \(1\)。
然后我们就可以根据这个来分情况解决,一种是两个一样多,那就 10101010,这个情况也可以 01010101,所以我们两个都要计算一下,然后取 min。
然后就是一个多一个少,就是 1010101 或者 0101010。
code:
#include <bits/stdc++.h>
#define int long long
#define N 200010
using namespace std;
int n, cnt1, num[N];
char s[N];
inline void solve1()
{
int ans = 0, pos = 1;
for(int i = 1; i <= n; i ++)
if(num[i] == 1) ans += abs(i - pos), pos += 2;
cout << ans << endl;
return ;
}
inline void solve2()
{
int ans = 0, pos = 2;
for(int i = 1; i <= n; i ++)
if(num[i] == 1) ans += abs(i - pos), pos += 2;
cout << ans << endl;
return ;
}
inline void solve3()
{
int ans1 = 0, ans2 = 0, pos = 1;
for(int i = 1; i <= n; i ++)
if(num[i] == 1) ans1 += abs(i - pos), pos += 2;
pos = 2;
for(int i = 1; i <= n; ++ i)
if(num[i] == 1) ans2 += abs(i - pos), pos += 2;
cout << min(ans1, ans2) << endl;
return ;
}
signed main()
{
scanf("%s", s + 1);
n = strlen(s + 1);
cnt1 = 0;
for(int i = 1; i <= n; i ++)
{
num[i] = s[i] - '0';
cnt1 += (num[i] == 1);
}
if(n % 2 == 1)
{
if(cnt1 > n - cnt1) solve1();
else solve2();
}
else solve3();
return 0;
}
T4
一开始考虑数位 dp,但是数据范围过大,而且可以不连续,所以考虑计数 dp。
我们发现可以根据模 \(9\) 的余数来判断一个子序列是否是 \(9\) 的倍数,所以分两种情况:
-
当前点不选,也就是 \(0\),那我们就直接加上前一个点的即可。
-
当前点选,那么我们就和之前 \(9\) 的余数组成一个两位数去取模,然后累加上去。
我们最后可以发现最后答案就是长度为序列长度,并且余数为 \(0\) 的个数。
code:
#include <bits/stdc++.h>
#define int long long
#define P 1000000007
#define N 200100
using namespace std;
char s[N];
int dp[N][10], ans;
signed main()
{
scanf("%s", s + 1);
int n = strlen(s + 1);
dp[0][0] = 1;
for(int i = 1; i <= n; i ++)
{
for(int j = 0; j < 9; j ++)
{
dp[i][j] += dp[i - 1][j]; //当前位填0
dp[i][(j * 10 + s[i] - '0') % 9] += dp[i - 1][j];//选当前数加上前面转移过来的方案数
dp[i][j] %= P;//取模
dp[i][(j * 10 + s[i] - '0') % 9] %= P;
}
}
ans = (dp[n][0] - 1 + P) % P;
cout << ans << endl;
return 0;
}
本文来自博客园,作者:北烛青澜,转载请注明原文链接:https://www.cnblogs.com/Multitree/articles/17521559.html
The heart is higher than the sky, and life is thinner than paper.
浙公网安备 33010602011771号