2026杭电多校1

2026杭电多校第一场

总结

项目 内容
赛时通过 A
赛后补题 E,F,J,D,H,L

A.小丑牌

Tag贪心

题意:略

题解

注意到 \(x*y\) 的最值取到时,\(x\)\(y\) 一定取到最值,分情况讨论即可

参考代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll x,y,n,m;
void solve() {
	cin>>x>>y>>n>>m;
	ll maxa=-1e11,mina=1e11,maxb=-1e11,minb=1e11;
	for(ll i=1,u;i<=n;i++) 
	{
		cin>>u;
		maxa=max(u,maxa);
		mina=min(u,mina);
	}
	for(ll i=1,v;i<=m;i++) 
	{
		cin>>v;
		maxb=max(v,maxb);
		minb=min(v,minb);
	}
	ll maxx=max(x+maxa,x);
	ll maxy=max(y+maxb,y);
	ll minx=min(x+mina,x);
	ll miny=min(y+minb,y);
	cout<<max({maxx*maxy,maxy*minx,maxx*miny,miny*minx})<<"\n";
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll T=1;
    cin>>T;
    while(T--) {
        solve();
    }
}


E. 摩卡数

Tag构造

题意 :构造字符串s使得其KMP自动机的fail树上跳跃的总次数等于给定值

题解

注意到字符只有两个时就已经可以满足题意,直接构造即可

参考代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
ll n;
bool check(ll x)
{
	if(x*(x+1)/2<=n) return 1;
	else return 0;
}
void solve()
{
    cin>>n;
    ll l=1,r=45000,mid;
    while(l<r)
    {
    	mid=(l+r+1)/2;
    	if(check(mid)) l=mid;
    	else r=mid-1;
	}
	ll len1=l+1;
	ll len2=(n-l*(l+1)/2);
	cout<<len1+len2<<" "<<"2"<<"\n";
	for(int i=1;i<=l+1;i++) cout<<"a";
	for(int i=1;i<=len2;i++) cout<<"b";
	cout<<"\n";
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}

F. 开关灯

Tag概率 期望

题意 :计算随机序列的期望

题解

这种题一般是利用期望的求和性质分解,(注意到连续段这一量是可分解的)

参考代码
#include<bits/stdc++.h>
using namespace std;
using i64=long long;
const i64 mod=998244353;
i64 inv6;
i64 qpow(i64 a,i64 p)
{
    i64 ans=1;
    while(p)
    {
        if(p&1) ans=ans*a%mod;
        a=a*a%mod;
        p>>=1;

    }
    return ans;
}
void solve()
{
    int n;
    cin>>n;
    vector<i64> a(n+1);
    i64 sum=0;
    for(int i=1;i<=n;i++) cin>>a[i],sum=(sum+a[i])%mod;
    i64 ans=(a[1]+a[n])%mod*inv6%mod;
    ans=(ans+1ll*(n+3)*inv6%mod*sum%mod)%mod;
    cout<<ans<<"\n";
    return;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    inv6=qpow(6,mod-2);
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}

J. 游戏

Tag博弈

题意 :略

题解

注意分类讨论的准确性,赛事16发wa警钟长鸣

参考代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
ll n,a[1000005];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    ll l=1,r=n;
    if(r-l==0)
    {
        cout<<"NO\n";
        return;
    }
    else if(r-l==1)
    {
        cout<<"YES\n";
        return;
    }
    else
    {
        if(n%2==0)
        {
            ll sum1=0,sum2=0;
            for(int i=1;i<=n/2;i++) sum1+=a[i];
            for(int i=n/2+2;i<=n;i++) sum2+=a[i];
            if(sum1>sum2) 
            {
                cout<<"YES\n";
                return;
            }
            else if(sum1<sum2)
            {
                cout<<"NO\n";
                return;
            }
            else
            {
                ll cnt1=0,cnt2=0;
                for(int i=n/2;i>=2;i--)
                {
                    cnt1+=a[i];
                    cnt2+=a[n+2-i];
                    if(cnt1!=cnt2)
                    {
                        if(cnt1<cnt2)
                        {
                            cout<<"YES\n";
                            return;
                        }
                        else
                        {
                            cout<<"NO\n";
                            return;
                        }
                    }
                }
            }
        }
        else
        {
            ll sum1=0,sum2=0;
            for(int i=1;i<=n/2;i++) sum1+=a[i];
            for(int i=n/2+2;i<=n;i++) sum2+=a[i];
            if(sum1>sum2) 
            {
                cout<<"YES\n";
                return;
            }
            else if(sum1<sum2)
            {
                cout<<"NO\n";
                return;
            }
            else
            {
                ll cnt1=0,cnt2=0;
                for(int i=n/2;i>=1;i--)
                {
                    cnt1+=a[i];
                    cnt2+=a[n+1-i];
                    if(cnt1!=cnt2)
                    {
                        if(cnt1<cnt2)
                        {
                            cout<<"YES\n";
                            return;
                        }
                        else
                        {
                            cout<<"NO\n";
                            return;
                        }
                    }
                }
                cout<<"NO\n";
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}

D.搭积木

Tag贪心

题意 :略

题解

首先发现合并某一个和他的父亲只取决于这个连通分支的 \(a_{i}/b_{i}\) ,那么我们可以用并查集维护连通分支,从而模拟合并的过程;

参考代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,ans;
struct node{
	ll a,b,fa,id;
}s[200005];
struct cmp {
	bool operator()(const node& a, const node& b) {
		return a.a*b.b<a.b*b.a;
	}
};
struct DSU {
	std::vector<ll> pa, size;
	
	explicit DSU(ll size_) : pa(size_), size(size_, 1) {
		std::iota(pa.begin(), pa.end(), 0);
	}
	
	ll find(ll x) { return pa[x] == x ? x : pa[x] = find(pa[x]); }
	
	void unite(ll x, ll y) {
		x = find(x), y = find(y);
		if (x == y) return;
		if (size[x] < size[y]) std::swap(x, y);
		pa[y] = x;
		size[x] += size[y];
	}
};
void solve() {
	cin>>n;
	for(ll i=1;i<=n;i++){
		cin>>s[i].a;
	}
	for(ll i=1;i<=n;i++){
		cin>>s[i].b;
	}
	for(ll i=1;i<=n;i++){
		cin>>s[i].fa;
	}
	for(ll i=0;i<=n;i++){
		s[i].id=i;
	}
	priority_queue<node,vector<node>,cmp> q;
	for(int i=2;i<=n;i++){
		q.push(s[i]);
	}
	DSU k(n+1);
	ans=0;
	ll cnt=0;
	while(cnt<n-1){
		node xn=q.top();
		q.pop();
		if(xn.a!=s[k.find(xn.id)].a) continue;
		if(xn.fa==0) continue;
		cnt++;
		ans+=s[k.find(xn.id)].a*s[k.find(xn.fa)].b;
		node nxt={s[k.find(xn.id)].a+s[k.find(xn.fa)].a,s[k.find(xn.id)].b+s[k.find(xn.fa)].b,s[k.find(xn.fa)].fa,0};
		k.unite(xn.id,xn.fa);
		s[k.find(xn.id)]=nxt;
		s[k.find(xn.id)].id=k.find(xn.id);
		q.push(s[k.find(xn.id)]);
	}
	cout<<ans<<"\n";
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll T=1;
    cin>>T;
    while(T--) {
        solve();
    }
}
posted @ 2026-08-21 23:58  pigeon666  阅读(4)  评论(0)    收藏  举报