ACDEFGHKLM 题解:
A World Final? World Cup! (I)
模拟即可
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--)
{
string s;
cin>>s;
int aa=0,bb=0;
s=" "+s;
int ans=1;
bool ok=false;
for(int i=1;i<=10;i++)
{
if(i%2==1)
{
if(s[i]=='1')
aa++;
if(aa>bb+5-ans+1)
{
cout<<i<<"\n";
ok=true;
break;
}
if(aa+5-ans<bb)
{
cout<<i<<"\n";
ok=true;
break;
}
}
else
{
if(s[i]=='1')
bb++;
if(bb>aa+5-ans)
{
cout<<i<<"\n";
ok=true;
break;
}
if(bb+5-ans<aa)
{
cout<<i<<"\n";
ok=true;
break;
}
ans++;
}
}
if(!ok)
{
if(aa!=bb)
cout<<10<<"\n";
else
cout<<-1<<"\n";
}
}
return 0;
}
C现在是,学术时间 (I)
直接模拟,或者看出来一人一篇文章即可
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
int ans=0;
int i=n+1;
int sum=n;
for(int j=1;j<=n;j++)
{
if(a[j]!=0)
{
i=j;
sum-=j-1;
break;
}
}
while(i<=n)
{
if(sum-a[i]>=0)
{
ans+=a[i];
sum-=a[i];
i+=a[i];
}
else
{
ans+=min(sum,a[i]);
break;
}
}
cout<<ans<<"\n";
}
return 0;
}
D现在是,学术时间 (II)
分类讨论即可,每次选四个顶点作为另一个顶点判断最值
#include<bits/stdc++.h>
using namespace std;
double x,y,xp,yp;
int t;
double iou;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--)
{
cin>>x>>y>>xp>>yp;
if(xp==x&&(yp==0||yp==y))
{
iou=1;
}
else if(yp==y&&(xp==0||xp==x))
{
iou=1;
}
else if(xp<=x&&yp<=y)
{
iou=max(xp*(y-yp),max(xp*yp,max((x-xp)*yp,(x-xp)*(y-yp))));
iou/=(x*y);
}
else if(xp>x&&yp>y)
{
iou=(x*y)/(xp*yp);
}
else if(xp>x)
{
iou=max((x*(y-yp))/(x*y+(xp-x)*(y-yp)),(x*yp)/(x*y+(xp-x)*yp));
}
else if(yp>y)
{
iou=max((xp*y)/(x*y+xp*(yp-y)),((x-xp)*y)/(x*y+(x-xp)*(yp-y)));
}
else
{
iou=(x*y)/(xp*abs(yp-y));
}
cout<<fixed<<setprecision(9)<<iou<<"\n";
}
return 0;
}
E鸡算几何
题解:(借鉴题解 | #2023牛客寒假算法基础集训营1#_牛客博客 (nowcoder.net))
首先把初始状态和最终状态的中点(B)平移至原点,然后将其中初始状态和最终状态的同一条边旋转至同一条坐标轴的同一个方向上,我选的(应该)是y轴正方向(由于边长不同,需要把边进行对应,也就是交换初始状态或最终状态的A、C点,体现在vector上就是翻转),最后考虑两种状态下的剩下一个点是否在y轴同侧,是就说明不一定需要操作三,否则必须使用操作三。
#include <bits/stdc++.h>
using namespace std;
using point_t=long double;
constexpr point_t eps=1e-8;
constexpr long double PI=3.1415926535897932384l;
template<typename T> struct point{
T x,y;
bool operator==(const point &a) const {return (abs(x-a.x)<=eps && abs(y-a.y)<=eps);}
bool operator<(const point &a) const {if (abs(x-a.x)<=eps) return y<a.y-eps; return x<a.x-eps;}
bool operator>(const point &a) const {return !(*this<a || *this==a);}
point operator+(const point &a) const {return {x+a.x,y+a.y};}
point operator-(const point &a) const {return {x-a.x,y-a.y};}
point operator-() const {return {-x,-y};}
point operator*(const T k) const {return {k*x,k*y};}
point operator/(const T k) const {return {x/k,y/k};}
T operator*(const point &a) const {return x*a.x+y*a.y;}
T operator^(const point &a) const {return x*a.y-y*a.x;}
int toleft(const point &a) const {const auto t=(*this)^a; return (t>eps)-(t<-eps);}
T len2() const {return (*this)*(*this);}
T dis2(const point &a) const {return (a-(*this)).len2();}
long double len() const {return sqrtl(len2());}
long double dis(const point &a) const {return sqrtl(dis2(a));}
long double ang(const point &a) const {return acosl(max(-1.0l,min(1.0l,((*this)*a)/(len()*a.len()))));}
point rot(const long double rad) const {return {x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad)};}
point rot(const long double cosr,const long double sinr) const {return {x*cosr-y*sinr,x*sinr+y*cosr};}
};
using Point=point<point_t>;
int main(){
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
cin>>T;
while(T--){
vector<Point> s(3),t(3);
for(auto &[x,y] : s){
cin>>x>>y;
}
for(auto &[x,y] : t){
cin>>x>>y;
}
if(abs(s[1].dis2(s[0]) - s[1].dis2(s[2])) <= eps) goto no;
if(abs(s[1].dis2(s[0]) - t[1].dis2(t[0])) > eps) reverse(t.begin(), t.end());
{
auto [dx,dy] = s[1];
for(auto &[x,y] : s){
x -= dx;
y -= dy;
}
auto d = s[1].dis(s[0]);
auto si = s[0].x/d , co = s[0].y/d;
for(auto &x : s){
x = x.rot(co,si);
}
}
{
auto [dx,dy] = t[1];
for(auto &[x,y] : t){
x -= dx;
y -= dy;
}
auto d = t[1].dis(t[0]);
auto si = t[0].x/d , co = t[0].y/d;
for(auto &x : t){
x = x.rot(co,si);
}
}
if(t[2].x*s[2].x<0 || t[2].y*s[2].y<0) goto yes;
else goto no;
if(0) yes: cout<<"YES"<<endl;
if(0) no: cout<<"NO"<<endl;
}
return 0;
}
F鸡玩炸蛋人
由于图不一定联通,那么当有不同联通块里都有ci!=0时,则输出0,最后还剩下ci全为0或者ci!=0的情况在同一个联通块里面,当ci全为0的时候,答案为每个连通块的大小的平方之和,当ci!=0的情况在同一个连通块里面时,答案为这个连通块的大小的平方。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,m,c[N],ss[N];
struct DSU {
std::vector<int> f, siz;
DSU(int n) : f(n), siz(n, 1) { std::iota(f.begin(), f.end(), 0); }
int leader(int x) {
while (x != f[x]) x = f[x] = f[f[x]];
return x;
}
bool same(int x, int y) { return leader(x) == leader(y); }
bool merge(int x, int y) {
x = leader(x);
y = leader(y);
if (x == y) return false;
siz[x] += siz[y];
f[y] = x;
return true;
}
int size(int x) { return siz[leader(x)]; }
};
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
DSU dsu(n+10);
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
dsu.merge(x,y);
}
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>c[i];
int fx=dsu.leader(i);
ss[fx]+=c[i];
sum+=c[i];
}
vector<bool>st(n+10,false);
if(sum==0)
{
int ans=0;
for(int i=1;i<=n;i++)
{
int xx=dsu.leader(i);
if(!st[xx])ans+=dsu.size(xx)*dsu.size(xx);
st[xx]=true;
}
cout<<ans;
return 0;
}
else
{
for(int i=1;i<=n;i++)
{
int xx=dsu.leader(i);
if(ss[xx]==sum)
{
cout<<dsu.size(xx)*dsu.size(xx);
return 0;
}
}
cout<<0;
}
}
G鸡格线
线段树,观察到每个数经过几次fx之后会变成一个不变值,然后用标记来标记是否是不变值。
//线段树4(结构体线段树,懒标记下传)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
int a[maxn];
int n,m;
struct tree
{
int l,r;
long long sum;
bool lazy;
}t[4*maxn+2];
void bulid(int p,int l,int r)
{
t[p].l=l;t[p].r=r;
if(l==r)
{
t[p].sum=a[l];
t[p].lazy=false;
return;
}
int mid=l+r>>1;
bulid(p*2,l,mid);
bulid(p*2+1,mid+1,r);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].lazy=(t[p*2].lazy&&t[p*2+1].lazy);
}
//区间修改[x,y]
void update(int p,int x,int y,int z,int k){
if(x<=t[p].l && y>=t[p].r)
{
if(t[p].lazy)return ;
if(t[p].l==t[p].r)
{
int summ=t[p].sum;
for(int i=1;i<=k;i++)
{
int next=round(10*sqrt(summ));
if(next==summ)
{
t[p].lazy=true;
break;
}
summ=next;
}
t[p].sum=summ;
return ;
}
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid) update(p*2,x,y,z,k);
if(y>mid) update(p*2+1,x,y,z,k);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].lazy=(t[p*2].lazy&&t[p*2+1].lazy);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
bulid(1,1,n);
while(m--)
{
int op;
cin>>op;
if(op==1)
{
int ll,rr,kk;
cin>>ll>>rr>>kk;
update(1,ll,rr,0,kk);
}
else
cout<<t[1].sum<<"\n";
}
return 0;
}
H本题主要考察了DFS
诈骗题,直接算出总的1和2计算min然后用10去直接减
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
void dfs(int x,int y)
{
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--)
{
cin>>n;
string s;
vector<int>v[n*n+10];
for(int i=1;i<=n*n-1;i++)
{
cin>>s;
for(int j=0;j<s.size();j++)
{
v[i].push_back(s[j]-'0');
}
}
int aa=0,bb=0;
for(int i=1;i<=n*n-1;i++)
{
for(auto x:v[i])
{
if(x==1)
aa++;
if(x==2)
bb++;
}
}
if(aa==bb)
{
cout<<10<<"\n";
}
else if(aa<bb)
{
cout<<10-(bb-aa)<<"\n";
}
else
{
cout<<10+(aa-bb)<<"\n";
}
}
return 0;
}
K本题主要考察了dp
直接构造100100......这样的字符串,可以保证坏区间最少,不需要dp
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6;
int n,a[N],m;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
//cin>>T;
while(T--)
{
cin>>n>>m;
int cnt=n-m;
int ans=n-2;
cnt/=2;
if(cnt==0)
{
cout<<n-2;
return 0;
}
m-=cnt;
if(m<=0)
cout<<0;
else
cout<<m-1;
}
return 0;
}
L本题主要考察了运气
求期望即可,为32
M本题主要考察了找规律
dp求即可
#include<bits/stdc++.h>
using namespace std;
double n,m;
double f[1000];
signed main()
{
scanf("%lf%lf",&n,&m);
for(int i=1;i<=n;++i)
for(int j=m;j;--j)
for(int k=1;k<=j;++k)
f[j]=max(f[j],f[j-k]+(1.0*k/(1.0*j)));
printf("%.8lf",f[int(m)]);
return 0;
}