题意:
给定一个字符串 s ,它的长度为 3 ,由大写字母和小写字母组成。
要求判断这个字符串是否为YES
(不分大小写)。
例如yES
、Yes
、yes
都是合法的。
思路:模拟
char a,b,c;
cin >> a >> b >> c;
bool f = false;
if(a == 'Y'||a=='y'){
if(b =='E'||b=='e'){
if(c=='S'||c=='s'){
f = true;
}
}
}
if(f)cout <<"yes"<<endl;
else cout <<"no"<<endl;
题意:
在一场比赛中,有 26 道题目和很多个团队,题目标号分别为 A
到 Z
。每当一道题目被第一次解决,该团队获得 2 个气球,否则获得 1 个气球。
现在给出一个字符串,代表题目被解决的顺序,字符串第 i 个字符 Si 代表题目 Si 被解决。求所有团队获得的气球总数。
思路:判断每个题目是不是第一次第一次解决,然后出现了几次。模拟
// Code Start Here
int t;
cin >> t;
while(t--){
map<char,bool> vis;
int cnt = 0;
int n;
cin >> n;
string s;
cin >> s;
for(auto op : s){
if(!vis[op]){
vis[op] = true;
cnt+=2;
}
else cnt += 1;
}
cout << cnt << endl;
}
题意:
有一把 n 个锁轮的锁,每个锁轮上写有数字 ai ,对于第 i 个锁轮,做了 bi 次操作。这些操作有两种类型:
U
:锁轮上的数字 +1 ,超过 9 则变为 0 。D
:锁轮上的数字 −1 ,小于 0 则变为 9 。
现在给定操作后的锁轮和操作,请你还原操作前的锁轮。
思路:考虑题目定义的进位的性质,发现只需要在0 和 10 的情况改为位即可。
// Code Start Here
int t;
cin >> t;
while(t--){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0;i<n;i++)cin >>a[i];
for(int i = 0;i<n;i++){
int tt;
cin >> tt;
string s;
cin >> s;
for(auto j :s){
if(j == 'D')a[i]++;
else a[i]--;
if(a[i] >= 10)a[i] -= 10;
else if(a[i] < 0)a[i] += 10;
}
}
for(int i = 0;i<n;i++)cout <<a[i] <<" ";
cout << endl;
}
题意:给出 n 个字符串 s1,s2⋯sn 每个字符串最多长 8,问对于每个 si(1≤i≤n) ,是否存在两个字符串 sj,sk(1≤j,k≤n)(j 可能等于 k)使得 si=sj+sk ,即 si 可以由 sj,sk 拼接得到。若存在,输出 1,否则输出 0。共 t 组数据。
思路:观察到 n < 1e5所以遍历显然超时,思考优化方式,发现两个字符串拼接方式只可能是a + b 或者b + a,只需要判断是否能作为子串出现即可,联想到可以判断两个子串是否在原始字符串群组里出现,分割然后遍历出现即可
// Code Start Here
int t;
cin >> t;
while(t--){
int n;
cin >> n;
vector<string> v(n);
map<string,bool> vis;
for(int i = 0;i<n;i++){
cin >> v[i];
vis[v[i]] = true;
}
vector<int> ans(n,0);
for(int i = 0;i<n;i++){
for(int j = 0;j<sz(v[i]);j++){
if(vis[v[i].substr(0,j+1)] && vis[v[i].substr(j+1,sz(v[i])-j-1)]){
ans[i] = 1;
}
}
}
for(int i = 0;i<n;i++)cout << ans[i];
cout << endl;
}
题意:给定一个 n×n (n≤100) 的 01 矩形,求至少修改多少次后能使矩形旋转 0°,90°,180°,270°后所形成的矩形都完全相同。
思路:我们发现对于矩阵旋转四次相同,即:每一位在操作以后形成的新位置上能保持原有的性质,只需要保证原来那个和他对应的即可,总共四个(除了中心以外最多四个),遍历一下然后看0多还是1多,把少的那个加入总操作次数即可
ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int z = 1; z <= n; z++) {
cin >>ch;
a[i][z] = ch - '0';
}
}
cnt1 = cnt2 = 0;
for (int i = 1; (i << 1) <= n; i++) {
for (int z = 1; (z << 1) <= n; z++) {
cnt1 = cnt2 = 0;
if (a[i][z] == 1) {
cnt1++;
} else {
cnt2++;
}
if (a[n - z + 1][i] == 1) {
cnt1++;
} else {
cnt2++;
}
if (a[n - i + 1][n - z + 1] == 1) {
cnt1++;
} else {
cnt2++;
}
if (a[z][n - i + 1] == 1) {
cnt1++;
} else {
cnt2++;
}
ans += min(cnt1, cnt2);
}
}
cnt1 = cnt2 = 0;
if (n & 1) {
for (int i = 1; (i << 1) <= n; i++) {
cnt1 = cnt2 = 0;
if (a[i][n / 2 + 1] == 1) {
cnt1++;
} else {
cnt2++;
}
if (a[n / 2 + 1][n - i + 1] == 1) {
cnt1++;
} else {
cnt2++;
}
if (a[n / 2 + 1][i] == 1) {
cnt1++;
} else {
cnt2++;
}
if (a[n - i + 1][n / 2 + 1] == 1) {
cnt1++;
} else {
cnt2++;
}
ans += min(cnt1, cnt2);
}
}
cout << ans << endl;
题意:给你一个序列a1,a2,…an 。请计算出满足下面条件的 (i,j)(1≤i,j≤n)个数 。
- ai<i<aj<j
思路:在最理想的情况,即:序列为0 1 2 3 4 5的情况,我们显然发现对于序列每一位所对应的“贡献”显然递增,即答案呈单调性。
因此我们可以遍历数组,记录一下当前的贡献,如果满足题意则根据上一个 + 1,否则维持原态,对于当前遍历到的再加入能加入贡献的最小值,即i - 1即可
// Code Start Here
int t;
cin >> t;
while(t--){
int n;
cin >> n;
vector<int> a(n+1);
vector<int> s(n+1,0);
int ans = 0;
for(int i = 1;i<=n;i++)cin >> a[i];
for(int i = 1;i<=n;i++){
if(a[i] < i) s[i] = s[i-1] + 1;
else s[i] = s[i-1];
if(a[i] >= 1 && a[i] < i) ans += s[a[i] - 1];
}
cout << ans << endl;
}
题意:
你有 n 个箱子。第 i 个箱子中有 ai 个硬币。你需要按照从箱子 1 号到箱子 n 号的顺序打开所有 n 个箱子。
你可以用以下两种钥匙之一打开一个箱子:
- 好钥匙:使用一次消耗 k 个硬币。
- 坏钥匙:使用时不消耗硬币,但会使所有未打开的箱子中的硬币数减半(包括正要打开的这个箱子)。硬币减半时向下取整。比如,用坏钥匙打开箱子 i 号时,ai=ai/2,ai+1=ai+1/2,......,an=an/2。
所有钥匙用过一次就会断掉(别想着买一把好钥匙开完所有箱子了),好钥匙需要重复付费,坏钥匙效果会重复计算。
也就是说,你总共需要使用 n 把钥匙,每个箱子用一把。开始时,你没有硬币和钥匙,如果想用好钥匙,你就得去买。值得注意的是,在这个过程中你可以赊账买钥匙;例如,如果你只有 1 个硬币,你也可以购买价值 k=3 个硬币的好钥匙,你的余额会变成 −2 个硬币。
你需要求出开完所有箱子之后你能获得的最大硬币数量
思路:
观察到每次使用坏钥匙在使用时会从当前开始(含)对后续的每个产生负的贡献,所以优先使用好钥匙。当不足以支付且后面/2的贡献大于K时,连续使用坏钥匙。
观察到每次从第i个开始使用坏钥匙的原始贡献是第i个之前的 所以可以采用前缀和来计算。
每次使用坏钥匙的次数不会大于 log2(MAX_subsquence)次,因为最大值/2这些次数会变成0,所以比他小的最大会产生这些贡献,时间复杂度O30 * n可以接受
// Code Start Here
int t;
cin >> t;
while(t--){
int n , k;
cin >> n >> k;
vector<int> a(n+1);
vector<int> s(n+1);
int max_val = -LINF;
for(int i = 1;i<=n;i++){
cin >> a[i];
s[i] = s[i-1] + a[i];
max_val = max(max_val,a[i]);
}
int ans = -LINF;
for(int i = 0;i<=n;i++){
int now = s[i];
int ctr = 1;
for(int j = i+1;ctr * 2 <= max_val && j<=n ;j++){
ctr *= 2;
now += a[j] / ctr;
}
now -= i * k;
ans = max(ans , now);
}
cout << max(ans,0LL) << endl;
// debug(ans);
}