2023大厂真题提交网址(含题解):
www.CodeFun2000.com(http://101.43.147.120/)
最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。
前言:一天独立AK两场DIV3就离谱。。造成了一种我没那么垃圾的假想.
E.思维.数学
题目大意:
石头剪刀布.已知Alice会分别会出 a , b , c a,b,c a,b,c次,已知Bob会求出 x , y , z x,y,z x,y,z次。但是顺序不确定。现在让你安排顺序使得Alice 赢得最多/赢得最少.
n ≤ 1 e 9 , a + b + c = x + y + z = n n\leq 1e9 , a+b+c=x+y+z=n n≤1e9,a+b+c=x+y+z=n
题目思路:
一.赢得最多很容易,贪心的算即可: m i n ( a , y ) + m i n ( b , z ) + m i n ( c , x ) min(a,y)+min(b,z)+min(c,x) min(a,y)+min(b,z)+min(c,x)即可.
二.赢得最少,考虑简单的鸽巢原理:
1.当
a
+
y
>
n
a+y > n
a+y>n时,无论怎么安排这个场次,一定会有
a
+
y
−
n
a+y-n
a+y−n场Alice会赢.
2.当
b
+
z
>
n
b+z > n
b+z>n时,无论怎么安排这个场次,一定会有
b
+
z
−
n
b+z-n
b+z−n场Alice会赢.
3.当
c
+
x
>
n
c+x > n
c+x>n时,无论怎么安排这个场次,一定会有
c
+
x
−
n
c+x-n
c+x−n场Alice会赢.
并且上述三者只会同时成立一个。因为若有两个成立,那么它们的和 > 2 n >2n >2n.与题目违背.
那么显然答案就是三者之间的最大值: m a x ( 0 , m a x ( a + y − n , m a x ( b + z − n , c + x − n ) ) ) max(0,max(a+y-n,max(b+z-n,c+x-n))) max(0,max(a+y−n,max(b+z−n,c+x−n)))
遗留问题:如何证明若三者同时不成立则一定不会有冲突。并且找出一种合法的不冲突构造方案.
F.计数dp
题目大意:
给你一个只含 a , b , c , ? a,b,c,? a,b,c,?的字符串. ? 可填写 a , b , c ?可填写a,b,c ?可填写a,b,c.现在问你对于所有可能的字符串,它们中总共含有多少个子序列 a b c abc abc.
n ≤ 2 e 5 n \leq 2e5 n≤2e5
题目思路:
考虑没有问号的情况:令 d p ( i , j ) dp(i,j) dp(i,j)代表前i个字符,有多少个子序列 r e s [ 1 → j ] res[1\rightarrow j] res[1→j], r e s = " a b c " res="abc" res="abc".
现在有问号加进来了,那么将状态升维,令 d p ( i , j , k ) dp(i,j,k) dp(i,j,k)代表前i个字符,且当前这个位置填写 ′ a ′ + j 'a'+j ′a′+j,有多少个子序列 r e s [ 1 → j ] res[1\rightarrow j] res[1→j], r e s = " a b c " res="abc" res="abc".
转移的时候多层循环即可。有个转移的细节是:
当当前位置填写a的时候,他这个位置对 [子序列’a’] 的个数的贡献应
该是:
3
x
3^x
3x.而不仅仅是
1
1
1.(x代表这个位置之前
?
?
? 的个数).
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
ll a[maxn];
ll dp[maxn][4][4];
int main()
{
ios::sync_with_stdio(false);
int t; t = 1;
while (t--){
ll n ; cin >> n;
string a; cin >> a;
a = '#' + a;
ll cnt = 1;
for (int i = 1 ; i <= n ; i++){
if (a[i] == '?') {
for (int e = 1 ; e <= 3 ; e++)
for (int j = 1 ; j <= 3 ; j++)
for (int k = 1 ; k <= 3 ; k++)
dp[i][e][j] = (dp[i][e][j] + dp[i - 1][k][j])%mod;
dp[i][1][1] = (dp[i][1][1] + cnt) % mod;
for (int j = 1 ; j <= 3 ; j++)
dp[i][2][2] = (dp[i][2][2] + dp[i - 1][j][1])%mod ,
dp[i][3][3] = (dp[i][3][3] + dp[i - 1][j][2])%mod;
cnt *= 3ll;
cnt %= mod;
}
else{
int v = a[i] - 'a' + 1;
for (int j = 1 ; j <= 3 ; j++)
for (int k = 1 ; k <= 3 ; k++)
dp[i][v][j] = (dp[i][v][j] + dp[i - 1][k][j])%mod;
if (v == 1) dp[i][v][1] = (dp[i][v][1] + cnt) % mod;
else if (v == 2) {
for (int j = 1 ; j <= 3 ; j++)
dp[i][v][2] = (dp[i][v][2] + dp[i - 1][j][1])%mod;
}
else {
for (int j = 1 ; j <= 3 ; j++)
dp[i][v][3] = (dp[i][v][3] + dp[i - 1][j][2])%mod;
}
}
}
int ans = 0;
for (int i = 1 ; i <= 3 ; i++){
ans = (ans + dp[n][i][3])%mod;
}
cout << ans << endl;
}
return 0;
}