SZUACM2022招新积分赛Day2 总结
作者:互联网
SZUACM2022招新积分赛Day2 总结
很难过但还是来补题
这次给一些题目添上了图解
题目
下午
晚上
补题
A.Gym 103438A
一种非常巧妙的转移:
从后往前扫,考虑前缀
小:出现多种前缀 f[i - 1] = n - i //长度代表可能
同:相当于一个桥,过渡过去 f[i] = f[i + 1]
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
long long f[N], ans;
int main () {
int n;
cin >> n;
string s, t;
cin >> s >> t;
for (int i = n - 1; i >= 0; i --) {
if (s[i] > t[i])
continue;
if (s[i] < t[i])
f[i] = n - i;
if (s[i] == t[i])
f[i] = f[i + 1];
ans += f[i];
}
cout << ans;
}
//大佬的666dp
//从后往前扫,考虑前缀
//小:出现多种前缀 f[i - 1] = n - i //长度代表可能
//同:相当于一个桥,过渡过去 f[i] = f[i + 1]
//同:往后找小
//小:往后找小/同
//大:skip
//dp
//先找到第一个同一位置上s比t小的,然后
//往前:相同的可以统计进去
//往后:
//注意,一旦不符合条件就break,因为字串要连续
B. Gym 103438N
在那里模拟了半天,其实差的不多了
最后想复杂了,反而还绕路了
主题应该是当前b[i],我反过来传递成了res,所以假了
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int n, op;
int a[N], b[N];
signed main () {
cin >> n;
for (int i = 0; i <= n; i ++)
cin >> a[i];
for (int i = 0; i <= n; i ++)
cin >> b[i];
for (int i = n; i > 0; i --) {
int res = b[i] - a[i];
if (res < 0)
continue; //不用传递了
b[i] -= res;
res = (res + 1) / 2, b[i - 1] += res;
op += res;
}
for (int i = 0; i <= n; i ++)
if (b[i] > a[i]) {
op = -1;
break;
}
cout << op << endl;
}
//模拟
//每传到下一级,op+=res,res*=2
//从后往前看需求 (ci+1)/2
//n+1种尺寸:A0,A1,...An
//现有:a0个A0,a1个A1...
//至少要有:b0个A0,b1个A1...
//op:A_i->2*A_{i + 1}
//先保证前面的,再往后拆分
//eg
//1006+498+244+10
挺可惜的,逻辑还是理的不太清楚
C. CodeForces 1672A
简单博弈,总次数为偶数就后手胜
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int n;
int a[N];
void solve () {
int op= 0;
cin >> n;
for (int i= 1; i <= n; i ++) {
int x;
cin >> x;
op += x - 1;
}
if (op % 2 == 0)
cout << "maomao90" << endl;
else
cout << "errorgorn" << endl;
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
实在惭愧,这是原题,然而我忘了。。。
A. 51Nod 1001
签到题,却WA了三次。。
直接i j 两头找就行了
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 50005;
int n, k;
int a[N];
signed main () {
cin >> k >> n;
for (int i = 1; i <= n; i ++)
cin >> a[i];
sort (a + 1, a + n + 1);
bool flag = false;
for (int i = 1, j = n; i < j; ) {
if (a[i] + a[j] == k) {
flag = true;
cout << a[i] << ' ' << a[j] << endl;
i ++, j --;
}
if (a[i] + a[j] < k)
i ++;
if (a[i] + a[j] > k)
j --;
}
if (!flag)
cout << "No Solution" << endl;
}
//-4 -3 -2 -1
B.51Nod - 1105
二分
注意细节,详见代码注释
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 50005;
ll a[N], b[N];
int n, k;
int check (ll x) {
int cnt = 0, j = n;
for (int i = 1; i <= n; i ++) {
while (a[i] * b[j] > x)
j --;
cnt += n - j; //因为最后再减了一次,所以免去那个+1
}
return cnt;
}
int main () {
scanf ("%d%d", &n, &k);
for (int i = 1; i <= n; i ++)
scanf ("%lld%lld", &a[i], &b[i]);
sort (a + 1, a + n + 1);
sort (b + 1, b + n + 1);
ll l = a[1] * b[1], r = a[n] * b[n];
while (l < r) {
ll mid = l + r >> 1;
if (check (mid) < k)
r = mid;
else
l = mid + 1;
}
printf ("%lld", r);
}
//。。。就是二分
//再优化:固定一个,枚举另一个
//若满足,则中间一整段都满足
//画个图
//若a[i]*b[j]>x,则b[j]之后所有b[i]也必定满足a[i]*b[j]
//长度为n-j+1(因为j在往回跳,所以最终为n-j)
E. Gym 102992K
构造,由重要性质\(gcd(i, i+1)=1\)可以想到整体偏移来构造。
具体如下:
得Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, k;
int main () {
cin >> n >> k;
if (k == 0 ) {
cout << -1;
return 0;
}
int st = 2;
for (int i = 1; i <= n; i ++) {
if (i == k)
cout << 1;
else
cout << st ++;
if (i != n)
cout << ' ';
}
}
//注意一个重要性质gcd(i,i+1)=1
//所以构造方法为把1放在k位置上,
//然后以此为分界线在此之前的前移,后面的不变
//行末不能有空格!!!!!
标签:招新,const,cout,int,res,Day2,long,SZUACM2022,using 来源: https://www.cnblogs.com/CTing/p/16299603.html