A. Acacius and String
题目链接
https://codeforces.com/contest/1379/problem/A
思路
解题的时候觉得太暴力了,以为有更好的方法就直接放弃了,结果真的就是暴力(哭辽)
(字符串与‘abacaba’暴力匹配(?不算匹配成功)记为函数count)
1、首先直接count,如果匹配到成功的次数大于2,直接输出NO,成功次数等于1书输出YES,并且将字符串的?替换成除abc外任意字符,成功次数为0考虑处理?后进行匹配。
2、对字符串进行暴力匹配(处理?),首先将匹配字段的?改成尽可能的匹配的字符,然后再count,返回值为1的话即为匹配成功,输出YES并且将剩余的?换成除abc外任意字符。返回值不为1则字符串回溯重新继续匹配。
代码
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const double pi = acos(-1.0);
#define INF 0x3f3f3f3f
// #define TDS_ACM_LOCAL
inline void read(int &x) {
char ch = getchar(); int f = 1; x = 0;
while (!isdigit(ch) && ch^'-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x *= f;
}
int t, n;
string s="abacaba", s2;
int count(string str){
int flag, ans=0;
for(int i=0; i<=str.size()-7; i++){
flag=1;
for(int j=0; j<7; j++)
if(str[i+j]!=s[j]) {flag=0; break;}
if(flag)
ans++;
}
return ans;
}
void print(string str){
cout<<"YES"<<endl;
for(int i=0; i<str.size(); i++){
if(str[i]=='?') str[i]='z';
cout<<str[i];
}
cout<<endl;
}
void solve(){
read(n);
cin>>s2;
int k=count(s2), flag, fflag=0;
if(k>1) {cout<<"NO"<<endl; return ;}
if(k==1) {print(s2); return ;}
string temp=s2;
for(int i=0; i<=s2.size()-7; i++){
s2=temp;
flag=1;
for(int j=0; j<7; j++){
if(s2[i+j]=='?') s2[i+j]=s[j];
if(s2[i+j]!=s[j]) {flag=0; break;}
}
if(flag){
k=count(s2);
if(k==1) {print(s2); fflag=1;}
}
if(fflag)
break;
}
if(!fflag) cout<<"NO"<<endl;
return ;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef TDS_ACM_LOCAL
freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
read(t);
while(t--) solve();
return 0;
}
B. Dubious Cyrpto
题目链接
https://codeforces.com/contest/1379/problem/B
思路
首先将b-c从等式中分离开考虑,它可以使na在以自身为中心的 [ l - r , r - l ] 范围内波动。
对于m的处理,可以m=na+(波动区间),所以在区间 [ l , r ] 枚举a的取值,得m%a(基于n),a-m%a(基于n+1)将取模后的范围分为0->m%a和a-m%a->a再判断值是否在波动区间内再对b和c的取值进行考虑
注:首先应该考虑a-m%a,因为这种情况n必为正整数。
代码
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const double pi = acos(-1.0);
#define INF 0x3f3f3f3f
typedef long long LL;
// #define TDS_ACM_LOCAL
LL l, r, m, t;
LL a, b, c;
LL c1, c2;
void solve(){
cin>>l>>r>>m;
for(int i=l; i<=r; i++){
c1=m%i, c2=i-m%i;
a=i;
if(c2<=r-l) {b=l, c=l+c2; break;}
if(c1<=r-l) {b=l+c1, c=l; break;}
}
cout<<a<<" "<<b<<" "<<c<<endl;
return ;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef TDS_ACM_LOCAL
freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
cin>>t;
while(t--) solve();
return 0;
}
C. Choosing flowers
题目链接
https://codeforces.com/contest/1379/problem/C
思路
按照a对花的价值进行非递增排序,枚举选a的每种情况,因为a可能大于b,所以二分求得当前枚举的b在a中排序后的位置,在n的范围内买下大于b的a,然后剩下的n买b,在买b前判断一下该枚举值的a是否购买,可以用前缀和维护一下二分得到b在a的位置时需要加上的sum_a
代码
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5 + 9;
// #define TDS_ACM_LOCAL
pair<long long, long long>x[N];
int t, n, m;
int find(long long v){
int l=1, r=m, ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(x[mid].first>v) {ans=mid, l=mid+1;}
else r=mid-1;
}
return ans;
}
void solve(){
int ind=0, cnt=0, hb=0;
long long sum[N]={0};
long long res=0, ans=0;
cin>>n>>m;
for(int i=1; i<=m; i++) {cin>>x[i].first>>x[i].second;}
sort(x+1, x+1+m, greater<pair<long long,long long>>()); //从大到小排序
for(int i=1; i<=m; i++) {sum[i]+=sum[i-1]+x[i].first;} //求前缀和
for(int i=1; i<=m; i++){
ind=find(x[i].second); //二分求得b在排好序后a的位置
cnt=min(ind, n-1); //在n的有效范围内买a
res=sum[cnt];
hb=n-cnt; //n的剩余值去买b
if(i>cnt) {res+=x[i].first; hb--;} //判断当前枚举的a是否购买
res+=1LL *hb*x[i].second;
ans=max(ans, res); //求得枚举的最大价值
}
cout<<ans<<endl;
return ;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef TDS_ACM_LOCAL
freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
cin>>t;
while(t--) solve();
return 0;
}