Educational Codeforces Round 178 (Rated for Div. 2)
A. Three Decks
满足;两个条件即可:
- 总和是3的倍数
- c的值大于sum/3
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int a,b,c;
cin>>a>>b>>c;
int sum=0;
sum=a+b+c;
int t=sum/3;
if(t*3!=sum){
cout<<"NO\n";
return;
}
if(a>t || b>t){
cout<<"NO\n";
return;
}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
B. Move to the End
对于每个下标为i的后缀,有两种情况:
- 不改变,答案为suf[i]
- 改变,可以把前i-1个数中的最大值换过来,答案为suf[i+1]+maxpre[i-1]
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
vector<int>a(n+10),pre(n+10),suf(n+10),sum(n+10);
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=max(pre[i-1],a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=n;i>=1;i--){
suf[i]=max(suf[i+1],a[i]);
}
for(int k=1;k<=n;k++){
int ans=sum[n]-sum[n-k];
int tmp=sum[n]-sum[n-k+1]+pre[n-k+1];
ans=max(ans,tmp);
cout<<ans<<" ";
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
C. Card Game
重点在于1和n上。
如果一个人同时持有1和n,则必胜。
如果Alice有1无n:
- 如果Bob只有n一张牌,则Alice必胜,因为Alice可以出1,Bob只能出n。
- 否则Bob胜,因为Alice无论出什么牌,Bob都有能战胜的牌。
如果Alice有n无1:
- 如果Alice只有n一张牌,则Bob必胜。
- 如果第n-1张牌是Bob的,则Bob必胜,因为如果Alice出n,Bob可以出1,如果Alice出其他牌,Bob可以出n-1。
- 否则Alice胜。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
string s;
cin>>s;
s=" "+s;
int cnta=0,cntb=0;
for(int i=1;i<=n;i++){
if(s[i]=='A') cnta++;
else cntb++;
}
if(s[1]==s[n]){
if(s[1]=='A'){
cout<<"Alice"<<endl;
}else{
cout<<"Bob"<<endl;
}
return;
}else{
if(s[1]=='A'){
//Alice 有1无n
if(cntb==1){
cout<<"Alice"<<endl;
}else{
cout<<"Bob"<<endl;
}
}else{
//Alice 有n无1
if(cnta==1 || s[n-1]=='B'){
cout<<"Bob"<<endl;
}
else{
cout<<"Alice"<<endl;
}
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
D. Array and GCD
赛时又花了一些时间看懂题干描述是什么意思
质数筛的模板还是错的,浪费了好长时间
首先,删除一些数之后的数组,是可以随意分配数值,且可以让总和变小的,只需要保证每个数不小于2.
所以一定要让每个数都是指数,为了每个数都能变成质数,则需要让这k个数的总和不大于前k个质数的总和
所以如果原数组的总和,大于前n个质数的总和,则删去最大数,直到符合条件。
题目需要筛出4e5的质数,而1-n范围内的质数大概有n/ln(n)个
我直接筛到了5e7,其实完全不用这么大
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
//using i128 = __int128_t;
const ll inf = 1e18;
const int mod = 998244353;
const int N=1e7;
const int M=4e5+10;
const int maxn = 1e8 + 5;
vector<int> Prime;
bool vis[maxn];
int pre[M];
void init() {
vis[1] = 1;
int n=maxn/2;
for (int i = 2; i <= n; ++i) {
if (vis[i] == 0)
Prime.push_back(i);
for (auto p : Prime) {
if (i * p > n)
break;
vis[i * p] = 1;
if (i % p == 0)
break;
}
}
pre[1]=2;
for(int i=2;i<M;i++){
pre[i]=pre[i-1]+Prime[i-1];
}
}
void solve(){
int n;
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a.begin()+1,a.end(),greater<int>());
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
}
for(int i=n;i>=1;i--){
if(a[i]>=pre[i]){
cout<<n-i<<endl;
return;
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
init();
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
E. Unpleasant Strings
赛时见到题,还以为是什么奇奇妙妙的字符串算法题,觉得不可做于是直接去睡觉,哎,,
其实得到答案主要分两部分,第一部分是在主串中找到子串的子序列,第二部分是计算在第一步找到的子序列最后的位置,至少需要加几个字符,能保证一定跳出主串。
第一部分:
需要对主串每个位置i,处理出当前位置的下一个字符j所在的位置,记为next[i][j],这一步的代码实现从后往前处理即可,的复杂度是26n。
假设子串的第一个字符是j,则直接从next[0][j]开始,跳到子串的最后一个字符即可。
第二部分:
dp[i]表示从i开始,至少需要加几个字符才能跳出主串(跳到n+1的位置)。
状态转移非常好想,只要枚举下次跳到的字符j来更新dp值即可。枚举j:
dp[i] = min ( dp[ next[i][j] ] + 1 )
点击查看代码
#include<bits/stdc++.h>
// #define int long long
using namespace std;
using pii=pair<int,int>;
using ll=long long;
const ll inf=1e9;
const int mod =1e9+7;
void solve(){
int n,k;
cin>>n>>k;
string s;
cin>>s;
s=" "+s;
vector<vector<int>> ne(n+10,vector<int>(k+10));
for(int i=1;i<=k;i++){
ne[n+1][i]=n+1;
}
// 处理出每个位置的下一个字符1-k在哪里
for(int i=n;i>=0;i--){
for(int j=1;j<=k;j++){
ne[i][j]=ne[i+1][j];
}
ne[i][s[i+1]-'a'+1]=i+1;
}
//dp[i]表示从这出发到n+1要走几步
vector<int> dp(n+10,inf);
dp[n+1]=0;
for(int i=n;i>=0;i--){
for(int j=1;j<=k;j++){
dp[i]=min(dp[i],1+dp[ne[i][j]]);
}
}
int q;
cin>>q;
while(q--){
string t;
cin>>t;
int now=0;
for(auto ch:t){
now=ne[now][ch-'a'+1];
}
cout<<dp[now]<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}

浙公网安备 33010602011771号