AtCoder Beginner Contest 418 (A - E)
A - I'm a teapot
点击查看代码
#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;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
string s;
for(int i=1;i<=n;i++){
char ch;
cin>>ch;
if(i>n-3){
s.push_back(ch);
}
}
if(s=="tea"){
cout<<"Yes\n";
}
else{
cout<<"No\n";
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
B - You're a teapot
暴力枚举每一对 \(l,r\) 即可可以用前缀和维护快速得到一段区间内部 t 的数量
点击查看代码
#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;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
string s;
cin>>s;
int n=s.size();
s=" "+s;
vector<int> a(n+1),pre(n+1);
for(int i=1;i<=n;i++){
a[i]=(s[i]=='t');
pre[i]=pre[i-1]+a[i];
}
double ans=0;
for(int i=1;i<=n;i++){
for(int j=i+2;j<=n;j++){
if(!a[i] || !a[j]) continue;
double tmp=(pre[j]-pre[i-1])-2;
tmp/=(double)(j-i+1)-2;
ans=max(ans,tmp);
}
}
printf("%.11lf",ans);
}
signed main(){
// ios::sync_with_stdio(0);
// cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
C - Flush
先排序,所有比 \(b\) 小的数都可以全部选完,所有比 \(b\) 大的数都可以选 \(b-1\) 个,此时再从比 \(b\) 大的数中任选一个,这个茶包的数量恰好是 \(b\)。排序后二分即可
如果 \(b>a[n]\) 则不可获胜
点击查看代码
#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;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,q;
cin>>n>>q;
vector<int> a(n+1),pre(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a.begin()+1,a.end());
for(int i=1;i<=n;i++){
pre[i]=a[i]+pre[i-1];
}
while(q--){
int x;
cin>>x;
if(x>a[n]){
cout<<-1<<endl;
continue;
}
int pos=lower_bound(a.begin()+1,a.end(),x)-a.begin();
pos--;
//第一个小于x的位置
int ans=pre[pos];
ans+=1+(n-pos)*(x-1);
cout<<ans<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
D - XNOR Operation
前置知识:如果区间长度为奇数,则区间 \(XNOR\) 等于 \(XOR\),否则等于 \(XOR\) 按位取反
所以对每个区间右端点 \(r\):
-
要找到有多少个左端点满足长度是奇数且区间异或和为 \(1\)
-
要找到有多少个左端点满足长度是偶数且区间异或和为 \(0\)
设 \(f[i] [j]\) 表示在奇数位置(\(i==1\))/ 偶数位置(\(i==0\))且前缀异或和为 \(j\) 的数量
当到位置 \(r\) 时
情况 \(1\),区间长度是奇数,$XOR(l,r)=prexor[r] ~~~ XOR ~~~ prexor[l-1] $
且 \(prexor[l-1]\) 的值和 \(prexor[r]\) 的值不同(值不同所以异或值为1)
同时因为区间长度是奇数,所以 \(l,r\) 奇偶性相同,所以 \(l-1,r\) 奇偶性不同
所以此时符合条件的 \(l\) 个数即为 $f[ (i ~ and ~ 1) ~ xor ~1] [pre[i]~ xor ~ 1] $
\((i ~ and ~ 1) ~ xor ~1\) 表示与 \(r\) 奇偶性不同的位置,\(pre[i]~ xor ~ 1\) 表示与 \(prexor[r]\) 前缀异或和值不同
情况 \(2\) 同理,符合条件的 \(l\) 个数为 $f[i ~ and ~ 1] [pre[i]] $
这种写法理解起来比较复杂,推荐 DP 写法,简单粗暴
点击查看代码
#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;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
string s;
cin>>s;
vector<int> a(n+1),pre(n+1);
for(int i=1;i<=n;i++){
a[i]=(s[i-1]=='1');
pre[i]=a[i]^pre[i-1];
}
int ans=0;
int cnt[2][2];
memset(cnt,0,sizeof cnt);
cnt[0][0]++;
for(int i=1;i<=n;i++){
int p=i&1;
ans+=cnt[p][pre[i]];
ans+=cnt[p^1][pre[i]^1];
cnt[i&1][pre[i]]++;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}
E - Trapezium
不存在三点共线,所以梯形的数量即为两两平行的线段数量
但平行四边形会被计算两次,所以还要减掉一次平行四边形的数量
对于平行线段,维护线段斜率即可
对于平行四边形,如果两个对角线的中点重合,则可以构成一个平行四边形,所以维护线段中点即可
注意维护时使用 \(map\) 会超时,需要用 \(vector + sort\)
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using pdd=pair<double,double>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
//返回斜率对应的pii
pii get(pii a,pii b){
int x=a.second-b.second, y=a.first-b.first;
if(x==0){
return {0,1};
}
if(y==0){
return {1,0};
}
int g=__gcd(abs(x),abs(y));
x/=g,y/=g;
if(x<0){
x=-x;
y=-y;
}
return {x,y};
}
void solve(){
int n;
cin>>n;
vector<pii> a(n+1);
for(int i=1;i<=n;i++){
cin>>a[i].first>>a[i].second;
}
int ans=0;
vector<pii> mp,cnt;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
pii k=get(a[i],a[j]);
mp.push_back(k);
int x=(a[i].first+a[j].first);
int y=(a[i].second+a[j].second);
cnt.push_back({x,y});
}
}
sort(mp.begin(),mp.end());
sort(cnt.begin(),cnt.end());
pii t={-inf,-inf};
int now=-1;
for(auto p:mp){
if(p==t) now++;
else{
if(now==-1){
now=1;
t=p;
}
else{
ans+=(now)*(now-1)/2;
now=1;
t=p;
}
}
}
if(now>0) ans+=(now)*(now-1)/2;
t={-inf,-inf};
now=-1;
for(auto p:cnt){
if(p==t) now++;
else{
if(now==-1){
now=1;
t=p;
}
else{
ans-=(now)*(now-1)/2;
now=1;
t=p;
}
}
}
if(now>0) ans-=(now)*(now-1)/2;
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
// cin>>ct;
while(ct--){
solve();
}
return 0;
}

浙公网安备 33010602011771号