Educational Codeforces Round 178 div2(题解ABCDE)

A. Three Decks

#1.由于最后三个数会相等,提前算出来和,%3判断,再判前两个数是否大于

cpp 复制代码
#include<iostream>
#include<vector>
#include<stdio.h>
#include<map>
#include<string>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
#include<array>
#include<cmath>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<iomanip>
using namespace std;
using ll = long long;
using llu = unsigned long long;
const ll inf = 0x3f3f3f3f3f3f3f3fll;
const ll MIN = -9187201950435737472ll;
ll mod = 1e9 + 7;
ll base = 131;
const int N = 1e4 + 10;
void solve()
{
	int a,b,c;cin>>a>>b>>c;
    if((a+b+c)%3==0)
    {
        int tmp=(a+b+c)/3;
        if((a<=tmp)&&(b<=tmp))cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    else cout<<"NO"<<endl;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t = 1;cin>>t;
	while (t--)
	{
		solve();
	}
	return 0;
}

B. Move to the End

我们每次要从数组末尾拿1,2,3...一直到n 个数,对于每次取,我都可以拿一个数到数组末尾。

#1.为此我们可以取一个前缀max数组,讨论从后向前的k个元素的前缀max是否大于这个元素

cpp 复制代码
#include<iostream>
#include<vector>
#include<stdio.h>
#include<map>
#include<string>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
#include<array>
#include<cmath>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<iomanip>
using namespace std;
using ll = long long;
using llu = unsigned long long;
const ll inf = 0x3f3f3f3f3f3f3f3fll;
const ll MIN = -9187201950435737472ll;
ll mod = 1e9 + 7;
ll base = 131;
const int N = 1e4 + 10;
void solve()
{
	int n;cin>>n;
    vector<ll>a(n+1);
    vector<ll>pre(n+1,0);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        pre[i]=max(pre[i-1],a[i]);
    }
    ll sum=0;
    for(int i=n;i>=1;i--)
    {
        sum+=a[i];
        if(pre[i-1]>a[i])cout<<sum-a[i]+pre[i-1]<<" ";
        else cout<<sum<<" ";
    }
    cout<<endl;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t = 1;cin>>t;
	while (t--)
	{
		solve();
	}
	return 0;
}

C. Card Game

有n张卡,编号大的克制编号小的,特别的1克制n,每回合Alice先出,Bob后手,如Alice克制Bob则得Alice得这两张牌,反之Bob

#1.注意到由于Alice先手,只有无论Alice出任何牌Bob都能克制她时,Bob胜,其余情况Alice胜

#2.可以用vector存Alice的牌,set存Bob的牌,二分+特判

cpp 复制代码
#include<iostream>
#include<vector>
#include<stdio.h>
#include<map>
#include<string>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
#include<array>
#include<cmath>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<iomanip>
using namespace std;
using ll = long long;
using llu = unsigned long long;
const ll inf = 0x3f3f3f3f3f3f3f3fll;
const ll MIN = -9187201950435737472ll;
ll mod = 1e9 + 7;
ll base = 131;
const int N = 1e4 + 10;
void solve()
{
	int n;cin>>n;
    string s;cin>>s;
    vector<int>a;
    s="#"+s;
    set<int>st;
    bool tag=true;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='A')a.push_back(i);
        else st.insert(i);
    }
    int l=a.size();
    for(int i=0;i<l;i++)
    {
        if(a[i]==n)
        {
            if(!(st.count(1)))tag=false;
        }
        else
        {
            auto it=st.upper_bound(a[i]);
            if(a[i]==1)
            {
                if(*it==n)tag=false;
            }
            else
            {
                if(*it<a[i])tag=false;
            }
        }
    }
    if(tag)cout<<"Bob"<<endl;
    else cout<<"Alice"<<endl;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t = 1;cin>>t;
	while (t--)
	{
		solve();
	}
	return 0;
}

D. Array and GCD

给一个长为n的数组a,可以让数组中的任一元素减1,另一元素加1,也可只减不加,最后问最少删几个元素能让数组任意两个元素之间互质,(删元素要在操作之前),并且要保证操作后的数组中任意元素都是>=2的

#1. 要让任意两个元素之间互素,当数组中都是素数即可

#2.再来考虑操作,我能让数组中任意元素变化,但数组的总和只能是不变或变小的,假设剩了x个元素,它最小应该是前x个素数相加。

#3.到这只需用欧拉筛筛到1e7(大概6e5个素数),在对素数做前缀和,即为保留i个元素,i个元素的总和至少为多少

#4.保持贪心性质,删数只删最小的

cpp 复制代码
#include<iostream>
#include<vector>
#include<stdio.h>
#include<map>
#include<string>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
#include<array>
#include<cmath>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<iomanip>
using namespace std;
using ll = long long;
using llu = unsigned long long;
const ll inf = 0x3f3f3f3f3f3f3f3fll;
const ll MIN = -9187201950435737472ll;
ll mod = 1e9 + 7;
ll base = 131;
const int N = 1e7 + 10;
const int M=1e6+4;
bool vis[N];
vector<int>primes;
ll pre[M];
void init(int x)
{
    vis[0]=vis[1]=true;
    for(int i=2;i<=x;i++)
    {
        if(!vis[i])primes.push_back(i);
        int l=primes.size();
        for(int j=0;j<l&&primes[j]*i<=x;j++)
        {
            vis[i*primes[j]]=true;
            if(i%primes[j]==0)break;
        }
    }
}
void solve()
{
	int n;cin>>n;
    vector<int>a(n+1);
    ll sum=0;
    for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
    sort(a.begin()+1,a.end(),greater<int>());
    if(n<2)
    {
        cout<<0<<endl;
        return;
    }
    for(int i=n;i>=2;i--)
    {
        if(sum>=pre[i])
        {
            cout<<n-i<<endl;
            return;
        }
        sum-=a[i];
    }
    cout<<n-1<<endl;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t = 1;cin>>t;
    init(1e7);
    int l=primes.size();
    //cout<<l<<endl;
    for(int i=0;i<l;i++)
    {
        pre[i+1]=pre[i]+primes[i];
    }
	while (t--)
	{
		solve();
	}
	return 0;
}

E. Unpleasant Strings

给一个长为n的字符串s,其中只能出现26个字母前k个字母,q次询问,每次询问给一个字符串,对于每次询问给出至少添加几个字母能使它不为s的子序列。

#1.对于本就不是它的子序列的字符串,添加0个。那就需要判断以一个字符串是否为另一个字符串的子序列。k很小,可以将每种字符用vector存起来,在判断时,只需要遍历要判断的字符串,二分对于这个字符出现序列中第一个大于上一个位置的位置

#2.通过上述方法可以找到这个字符串作为子序列第一个末尾,对于后续元素至少要添加的元素数量,我们可以采用后缀和提前预处理出答案,后缀和是从后向前遍历,将k个元素都出现的一段视作1,再做后缀和

cpp 复制代码
#include<iostream>
#include<vector>
#include<stdio.h>
#include<map>
#include<string>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
#include<array>
#include<cmath>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<iomanip>
using namespace std;
using ll = long long;
using llu = unsigned long long;
const ll inf = 0x3f3f3f3f3f3f3f3fll;
const ll MIN = -9187201950435737472ll;
ll mod = 1e9 + 7;
ll base = 131;
const int N = 1e4 + 10;
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int l,q,k;cin>>l>>k;
    string s;cin>>s;
    string str;
    vector<vector<int>>dp(k+1,vector<int>());
    vector<ll>suf(l+3,0);
    s="#"+s;
    for(int i=1;i<=l;i++)
    {
       dp[s[i]-'a'+1].push_back(i);
    }
    suf[l]=0;
    int cnt=0;
    vector<bool>vis(k+1,false);
    for(int i=l-1;i>=0;i--)
    {
        if(!vis[s[i+1]-'a'+1])cnt++,vis[s[i+1]-'a'+1]=true;
        suf[i]=suf[i+1]+(cnt==k);
        if(cnt==k)
        {
            fill(vis.begin(),vis.end(),false);
            cnt=0;
        }
    }
    cin>>q;
    while(q--)
    {
        cin>>str;
        int len=str.length();
        int pos=-1;
        bool tag=true;
        for(int i=0;i<len;i++)
        {
           int x=str[i]-'a'+1;
           auto tmp=upper_bound(dp[x].begin(),dp[x].end(),pos);
           //cout<<tmp<<endl;
           if(tmp==dp[x].end())
           {
              tag=false;
              break;
           }
           pos=*tmp;
           //cout<<pos<<endl;
        }
        if(!tag)
        {
            cout<<0<<endl;
            continue;
        }
        //cout<<pos<<endl;
        cout<<suf[pos]+1<<endl;
    }
	return 0;
}
相关推荐
耀耀_很无聊6 分钟前
02_使用 AES 算法实现文件加密上传至阿里云、解密下载
java·spring boot·算法·阿里云·云计算·aes·oss
共享家95271 小时前
C++模板知识
c++
阿沁QWQ1 小时前
友元函数和友元类
开发语言·c++
江沉晚呤时3 小时前
Redis缓存穿透、缓存击穿与缓存雪崩:如何在.NET Core中解决
java·开发语言·后端·算法·spring·排序算法
achene_ql3 小时前
缓存置换:用c++实现最近最少使用(LRU)算法
开发语言·c++·算法·缓存
predisw4 小时前
垃圾收集GC的基本理解
java·jvm·算法
奔跑的乌龟_4 小时前
L3-040 人生就像一场旅行
数据结构·算法
mahuifa4 小时前
(35)VTK C++开发示例 ---将图片映射到平面2
c++·vtk·cmake·3d开发
网络骑士hrg.4 小时前
题解:洛谷 CF2091E Interesting Ratio
算法
旺仔老馒头.4 小时前
【数据结构】线性表--顺序表
c语言·数据结构·visual studio