2025牛客寒假算法基础训练营4
K Tokitsukaze and Shawarma
签到题,三种时长去max即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 7;
const int inf = LLONG_MAX / 10;
const int mod = 998244353;
// #define x first
// #define y second
void miaojiachun(){
int x,y,z,a,b,c;
cin>>x>>y>>z>>a>>b>>c;
cout<<max(x*a,max(y*b,z*c))<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int ING = 1;
cin >> ING;
while (ING--) {
miaojiachun();
}
return 0;
}
I Tokitsukaze and Pajama Party
题目要求u和uwawauwa之间至少有一个字符,可以将所有uwawauwa所在的下标进行标记,再从右往左做一个前缀和。之后遍历字符串,对于每一个u所在的下标index,将前缀和下标为index+2的值累加进答案即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 7;
const int inf = LLONG_MAX / 10;
const int mod = 998244353;
// #define x first
// #define y second
void miaojiachun(){
int n;
cin>>n;
string s;
cin>>s;
vector<int>a(n);
for(int i=0;i<n;i++){
if(s[i]=='u'){
a[i]=1;
}
}
for(int i=1;i<n;i++){
a[i]=a[i]+a[i-1];
}
int sum=0;
for(int i=n-1;i>8;i--){
if(s[i]=='a' and s[i-1]=='w' and s[i-2]=='u' and s[i-3]=='a' and s[i-4]=='w' and s[i-5]=='a' and s[i-6]=='w' and s[i-7]=='u'){
sum+=a[i-9];
}
}
cout<<sum<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int ING = 1;
cin >> ING;
while (ING--) {
miaojiachun();
}
return 0;
}
E Tokitsukaze and Dragon's Breath
可以注意到龙之吐息的范围是一条正斜线与一条反斜线相交,并且任意一个点都可以释放龙之吐息。这意味着地图上每一个点都可以作为一条正斜线与一条反斜线相交。那么我们遍历正斜线与反斜线,并将每条斜线的怪物数量和加到斜线上的方格中,由于交点会重复计算,最终消灭的怪物数量还要减去交点方格的怪物数量。
遍历正斜线我用矩形左边与上边的方格为起点,令x++,y++,直到出界,反斜线同理。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 7;
const int inf = LLONG_MAX / 10;
const int mod = 1e9+7;
// #define x first
// #define y second
int a[1005][1005];
int b[1005][1005];
int c[1005][1005];
void miaojiachun(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
b[i][j]=c[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i>1 and j>1){
b[i][j]=a[i][j]+b[i-1][j-1];
}else{
b[i][j]=a[i][j];
}
}
}
for(int i=1;i<=n;i++){
for(int j=m;j>=1;j--){
if(i>1 and j<m){
c[i][j]=a[i][j]+c[i-1][j+1];
}else{
c[i][j]=a[i][j];
}
}
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// cout<<b[i][j]<<"\t";
// }
// cout<<endl;
// }
// cout<<endl;
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// cout<<c[i][j]<<"\t";
// }
// cout<<endl;
// }
int max1=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int sum=a[i][j];
if(i>1 and j>1){
sum+=b[i-1][j-1];
}if(i<n and j<m) {
int min1=min(abs(n-i),abs(m-j));
sum+=b[i+min1][j+min1]-b[i][j];
}
if(i>1 and j<m){
sum+=c[i-1][j+1];
}if(i<n and j>1){
int min1=min(n-i,j-1ll);
sum+=c[i+min1][j-min1]-c[i][j];
}
max1=max(sum,max1);
}
}
cout<<max1<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int ING = 1;
cin >> ING;
while (ING--) {
miaojiachun();
}
return 0;
}
D Tokitsukaze and Concatenate Palindrome
这题的字符顺序可以任意调换,只需要贪心地匹配字符即可。具体贪心方法如下:
先存入长的字符串的字母数量,再匹配短的字符串,匹配上相同的字符则存入的字母数量要减一,无法匹配的字符数量记为cnt1,这里记为两边的未匹配字母。长的字符串剩下的字母与其匹配后剩下的字母记为中间的字母,中间的字母数量和为奇数的字母记为中间的未匹配字母将其数量记为cnt2,中间未匹配的字母可以移到两边变为对应需要的字母。由于两边的未匹配字母由短的字符串产生,无法移动到中间,所以答案为
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 7;
const int inf = LLONG_MAX / 10;
const int mod = 1e9+7;
// #define x first
// #define y second
void miaojiachun(){
int n,m;
cin>>n>>m;
string a,b;
cin>>a>>b;
int sum=0;
int k=0;
int aa[26]={0};
int bb[26]={0};
for(int i=0;i<26;i++){
aa[i]=bb[i]=0;
}
for(int i=0;i<n;i++){
aa[a[i]-'a']++;
}
for(int i=0;i<m;i++){
bb[b[i]-'a']++;
}
int ans=0;
for(int i=0;i<26;i++){
sum+=min(aa[i],bb[i]);
}
// cout<<sum<<endl;
if(b.size()==sum){
for(int i=0;i<26;i++){
aa[i]-=bb[i];
if(aa[i]%2==1){
ans++;
}
}
cout<<ans/2<<endl;
return;
}if(a.size()==sum){
for(int i=0;i<26;i++){
bb[i]-=aa[i];
if(bb[i]%2==1){
ans++;
}
}
cout<<ans/2<<endl;
return;
}
int cj=abs(n-m);
if(cj<=1){
for(int i=0;i<26;i++){
ans+=abs(aa[i]-bb[i]);
}
cout<<ans/2<<endl;
}else{
if(n>m){
int kk=cj;
for(int i=0;i<26;i++){
if(aa[i]>bb[i]){
int zz=(aa[i]-bb[i]);
if(zz%2==1){
zz--;
}
kk-=zz;
if(kk<=1){
break;
}
}
}
if(kk<=1){
cout<<m-sum<<endl;
return;
}else{
cout<<(n-sum+m-sum-(cj-kk))/2<<endl;
return;
}
}else{
int kk=cj;
for(int i=0;i<26;i++){
if(bb[i]>aa[i]){
int zz=(bb[i]-aa[i]);
if(zz%2==1){
zz--;
}
kk-=zz;
if(kk<=1){
break;
}
}
}
if(kk<=1){
cout<<n-sum<<endl;
return;
}else{
cout<<(n-sum+m-sum-(cj-kk))/2<<endl;
return;
}
}
}
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int ING = 1;
cin >> ING;
while (ING--) {
miaojiachun();
}
return 0;
}
B Tokitsukaze and Balance String (easy)
数据范围较小,因此我们可以二进制枚举每一个 '?' 填什么。
之后再枚举每一个字符翻转后是否可以将字符串变平衡。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 7;
const int inf = LLONG_MAX / 10;
const int mod = 1e9+7;
// #define x first
// #define y second
pair<int, int> cz(const string& s) {
int cnt01 = 0, cnt10 = 0;
for (int i = 0; i < s.length() - 1; ++i) {
if (s[i] == '0' && s[i+1] == '1') {cnt01++;cnt01%=mod;}
if (s[i] == '1' && s[i+1] == '0') {cnt10++;cnt10%=mod;}
}
return {cnt01%mod, cnt10%mod};
}
int cal(const string& s) {
int val = 0;
for (int i = 0; i < s.length(); ++i) {
string temp = s;
temp[i] = (temp[i] == '0') ? '1' : '0';
auto [cnt01, cnt10] = cz(temp);
if (cnt01 == cnt10) {val++;val%=mod;}
}
return val%mod;
}
void miaojiachun(){
int n;
cin>>n;
string s;
cin>>s;
// if(n==1){
// cout<<1<<endl;
// return;
// }
vector<int>a;
for(int i=0;i<n;i++){
if(s[i]=='?'){
a.push_back(i);
}
}
int p=a.size();
int ans=0;
for(int i=0;i<(1<<p);i++){
string temp=s;
for(int j=0;j<p;j++){
if(i&(1<<j)){
temp[a[j]]='1';
}else{
temp[a[j]]='0';
}
}
ans+=cal(temp);
ans%=mod;
}
cout<<ans%mod<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int ING = 1;
cin >> ING;
while (ING--) {
miaojiachun();
}
return 0;
}
C Tokitsukaze and Balance String (hard)
1) 首尾相同的字符串一定是平衡的。
2) 首尾不相同的字符串一定是不平衡的。
记录字符串长度为 n ,字符串中'?'的数量为 cnt ,接下来需要使用。
接下来就是分类讨论:
1)字符串长度为 1:
- 字符串为'?',答案为 2.
- 否则,答案为 1。
直接特判结束。
2)字符串首尾都不是"?":
- 字符串首尾相同,那么字符串中间任意翻转一个都行(n-2)。
- 字符串首尾不同,那么字符串首尾任意翻转一个都行(2)。
答案记得乘上字符串的种类数,即要乘以 2^cnt
3)字符串首尾中有一个"?"
- 如果将首尾中的"?'填成首尾相同,那么字符串中间任意翻转一个都行(n-2)。
- 如果将首尾中的'?'填成首尾不同,那么字符串首尾任意翻转一个都行(2)。
答案就是两种情况相加后再乘上字符串的种类数,由于固定了首尾中的一个"?,最后还需要除以2,即 n x 2^(cnt-1)
4)字符串首尾都是'?’:
- 如果将首尾中的"?"填成首尾相同,那么字符串中间任意翻转一个都行(n-2)。
- 如果将首尾中的'?'填成首尾不同,那么字符串首尾任意翻转一个都行(2)。
答案就是两种情况相加后再乘上字符串的种类数,由于固定了首尾中的两个"?,导致最后首尾相同和不
同各有 2 种情况,最后还需要除以4后再乘以2,即n x2^(cnt-1)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef pair<int, int> PII;
const int N = 2e5 + 7;
const int inf = LLONG_MAX / 10;
const int mod = 1e9+7;
// #define x first
// #define y second
// 首尾相同的字符串一定是平衡的
// 首尾不相同的字符串一定是不平衡的
int qmi(int a,int b){
int res=1;
for(;b;b/=2,a=1ll*a*a%mod){
if(b%2){
res=1*res*a%mod;
}
}
return res;
}
void miaojiachun(){
int n;
cin>>n;
string s;
cin>>s;
if(n==1){
if(s[0]=='?'){
cout<<"2"<<endl;
return;
}else{
cout<<"1"<<endl;
return;
}
}
int kk=0;
for(int i=0;i<n;i++){
if(s[i]=='?'){
kk++;
}
}
int ans=qmi(2,kk);
int ans1=qmi(2,kk-1);
if(s[0]==s[n-1] and s[0]!='?'){
cout<<((n-2)*ans)%mod<<endl;
return;
}
if(s[0]!=s[n-1] and s[0]!='?' and s[n-1]!='?'){
cout<<(2*ans)%mod<<endl;
return;
}
if(s[0]==s[n-1] and s[0]=='?'){
int sum1=0,sum2=0;
sum1=((((n-2)*ans1)%mod))%mod;
sum2=((((2*ans1)%mod))%mod);
cout<<(sum1+sum2)%mod<<endl;
return;
}
int sum1=ans1*2%mod;
int sum2=ans1*(n-2)%mod;
cout<<(sum1+sum2)%mod<<endl;
}
signed main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int ING = 1;
cin>>ING;
while (ING--) {
miaojiachun();
}
return 0;
}

浙公网安备 33010602011771号