Codeforces Round #606(B-D)
作者:互联网
Dashboard - Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) - Codeforces
B. Make Them Odd
题意: 一个数组,每次选择一个数,将数组中的这个数都减半,问多少次数组就所有数字都是奇数
题解:将最后变成的奇数相同的数组分成一组,然后答案加上最大的呢个数需要多少次变成奇数即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=5e5+5; const ll inf=1e18; const ll mod=998244353; ll a[N]; unordered_map<ll,ll> mp,maxn; ll solve(ll x){//求出这个数组最后变成的奇数是几 ll pt=1; ll maxn=-inf; while(pt<x){ pt*=2; if(x%pt==0) maxn=max(maxn,pt); } return x/maxn; } signed main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); ll t;cin>>t; while(t--){ ll n;cin>>n; vector<ll> q; for(ll i=1;i<=n;i++){ cin>>a[i]; if(a[i]%2) continue; ll res=solve(a[i]); if(!mp[res]){ mp[res]=1;q.push_back(res); } maxn[res]=max(maxn[res],a[i]); } ll ans=0; for(ll i=0;i<q.size();i++){ ll pt=maxn[q[i]]/q[i]; while(pt>1){ pt/=2;ans++; } mp[q[i]]=maxn[q[i]]=0; } cout<<ans<<endl; } }
C. As Simple as One and Two
题意:给出一个字符串,每次选择一个字符删除,最后保证字符串中不出现“one"和”two",问最少删除几个字符。
题解:分情况讨论
- one和two单独出现的时候,删除中间的,这样可以防止出现”oneeee“这种情况。
- one和two一起出现,一种特殊情况,twone,这个时候我们删除中间的"o"。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=5e5+5; const ll inf=1e18; const ll mod=998244353; ll a[N]; unordered_map<ll,ll> mp,maxn; signed main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); ll t;cin>>t; while(t--){ string s;cin>>s; ll sum=0; vector<ll> ans; if(s.size()==1){ cout<<"0"<<endl<<endl; continue; } for(ll i=0;i<s.size()-2;){ if(s[i]=='o'&&s[i+1]=='n'&&s[i+2]=='e'){//单独出现 sum++;ans.push_back(i+1);i+=3; } else if(s[i]=='t'&&s[i+1]=='w'&&s[i+2]=='o'){//一起出现的特殊情况 if(i+4<s.size()){//确定好边界,防止访问越界 if(s[i+3]=='n'&&s[i+4]=='e'){ sum++;ans.push_back(i+2);i+=5; } else{ sum++;ans.push_back(i+1);i+=3; } } else{ sum++;ans.push_back(i+1);i+=3; } } else i++; } cout<<sum<<endl; for(ll i=0;i<ans.size();i++) cout<<ans[i]+1<<" "; cout<<endl; } }
D. Let's Play the Words?
题意:给出n个01字符串,将他们按照某种顺序排序,要求如果前一个字符串是什么结尾,后一个字符串就是什么开头。比如:前一个是001,1结尾后一个也要是1开头,可以选择将其中的一些字符串翻转,要求翻转后的字符串不能与原有的相同,问最少翻转几次
题解:分成几种类型的字符串,01,10,0,1,00,11,将其中00,0分为一类,11,1分为一类,首先,只要存在01,或者10,那么00,0,11,1一定能找到位置,所以我们只需要判断01和10即可,如果如果不存在01和10那么 {00,0}和{11,1}只能存在一个,如果存在01,10就判断能不能有正确答案即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=5e5+5; const ll inf=1e18; const ll mod=998244353; ll a[N]; string s[N]; ll sum[3][3],le[3]; unordered_map<string,ll> mp; signed main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); ll t;cin>>t; while(t--){ ll n;cin>>n; memset(sum,0,sizeof(sum));//清零 memset(le,0,sizeof(le)); mp.clear(); vector<ll> p,q; for(ll i=1;i<=n;i++){ cin>>s[i]; mp[s[i]]=1; if(s[i].size()==1) le[s[i][0]-'0']++;//存储0出现的位置 else sum[s[i][0]-'0'][s[i][s[i].size()-1]-'0']++;//存储1出现的位置 if(s[i][0]=='0'&&s[i][s[i].size()-1]=='1'&&s[i].size()>1) p.push_back(i);//存储01出现的位置 else if(s[i][0]=='1'&&s[i][s[i].size()-1]=='0'&&s[i].size()>1) q.push_back(i);//存储10出现的位置 } ll flag=0;//用来判断{00,0},和{11,1}出现的个数 ll pt=0; if(le[0]||sum[0][0]) flag++; if(le[1]||sum[1][1]) flag++; vector<ll> ans; if(sum[0][1]||sum[1][0]){ if(sum[0][1]>sum[1][0]){ ll px=(sum[0][1]+sum[1][0])/2; ll x=abs(sum[1][0]-px); ll cnt=0; for(ll i=0;i<p.size(),cnt<x;i++){ string st=s[p[i]]; reverse(st.begin(),st.end()); if(mp[st]) continue;//判断翻转后是否存在 ans.push_back(p[i]); cnt++; } if(cnt!=x){ pt=1; } } else{ ll px=(sum[0][1]+sum[1][0])/2; ll x=abs(sum[0][1]-px); ll cnt=0; for(ll i=0;i<q.size(),cnt<x;i++){ string st=s[q[i]]; reverse(st.begin(),st.end()); if(mp[st]) continue; ans.push_back(q[i]); cnt++; } if(cnt!=x){ pt=1; } } } else if(flag==2){//如果01,10一个也没有但是{00.0},{11,1}都存在则不可以 pt=1; } if(pt) cout<<"-1"<<endl; else { cout<<ans.size()<<endl; for(ll j=0;j<ans.size();j++) cout<<ans[j]<<" "; cout<<endl; } } }
标签:606,const,sum,Codeforces,Round,01,mp,ll,size 来源: https://www.cnblogs.com/hhzp/p/16645759.html