Educational Codeforces Round 125 (Rated for Div. 2)(A~E)

前几把天天坐牢,心态炸裂,3场掉了200+。

PS:(零点战神打破魔咒,真不容易)

A. Integer Moves(摸你/分类讨论)

我们发现答案必然<=2,因此只需分类即可

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll a[Ma];
int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
	{
		ll x,y;
		scanf("%lld%lld",&x,&y);
		ll ans=x*x+y*y;
		ll p=sqrt(ans);
		if (ans==0)
			printf("0\n");
		else if (p*p==ans)
			printf("1\n");
		else
			printf("2\n");
	}
	return 0;
}

B. XY Sequence(摸你)

只需保证局部最优即可

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll a[Ma];

int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
	{
		ll n,ma,x,y;
		scanf("%lld%lld%lld%lld",&n,&ma,&x,&y);
		ll ans=0;
		for (ll i=1;i<=n;i++)
		{
			if (a[i-1]+x>ma)
				a[i]=a[i-1]-y;
			else
				a[i]=a[i-1]+x;
			ans+=a[i];
		}
		printf("%lld\n",ans);
	}
	return 0;
}

C. Bracket Sequence Deletion(摸你/分类讨论)

我们可以发现一共有4种情况:

(),)),((,)(,对于前3种直接结束,对于第4种,回文串格式变为了)((((....(((),因此摸你即可

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;
ll n;
string s;

void sol()
{
	ll add=0,f=0;
	while (f+1<s.size())
	{
		if (s[f]=='(')
			add++,f+=2;
		else if (s[f+1]==')')
			add++,f+=2;
		else
		{
			ll flag=0;
			for (ll i=f+2;i<s.size();i++)
			{
				if (s[i]==')')
				{
					add++,flag=1;
					f=i+1;
					break;
				}
			}
			if (!flag)
				break;
		}
	}
	ll w=s.size()-f;
	printf("%lld %lld\n",add,w);
	return;
}

int main()
{
	ll tt;
	scanf("%lld",&tt);
	while (tt--)
	{
		cin>>n>>s;
		sol();
	}
	return 0;
}

D. For Gamers. By Gamers.(筛+二分答案)

首先我们发现问题变为花费k*ci,可以得到k*hi*di的贡献,因此变成了dp,而根据优化可以保证O(n*lnC)的dp。

我是根据离线算法O(n*lnC*logm)进行(以贡献为维度),事实上可以用在线算法(以花费为维度)进行,复杂度为O(n*lnc+m*logC)

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 1000005
#define mod 1000000007
using namespace std;

struct node
{
	ll c,w;
	bool operator <(const node &A)const{
		if (c==A.c)
			return w>A.w;
		return c<A.c;
	}
}t[Ma];

struct que
{
	ll num,w,ans;
	bool operator <(const que &A)const{
		return w<A.w;
	}
}a[Ma];

bool cmp(que x,que y)
{
	return x.num<y.num;
}

ll pp[Ma];
int main()
{
	ll n,C;
	scanf("%lld%lld",&n,&C);
	for (ll i=1;i<=n;i++)
	{
		ll H,D;
		scanf("%lld%lld%lld",&t[i].c,&H,&D);
		t[i].w=H*D;
	}
	sort(t+1,t+n+1);
	ll m;
	scanf("%lld",&m);
	for (ll i=1;i<=m;i++)
	{
		ll H,D;
		scanf("%lld%lld",&H,&D);
		a[i].w=H*D,a[i].num=i,a[i].ans=1e18;
	}
	sort(a+1,a+m+1);
	for (ll i=1;i<=m;i++)
		pp[i]=a[i].w;
	for (ll i=1;i<=n;i++)
	{
		if (t[i].c==t[i-1].c)
			continue;
		for (ll j=1;j<=C/t[i].c;j++)
		{
			ll ans=j*t[i].w;
			ll l=lower_bound(pp+1,pp+m+1,ans)-pp-1;
			a[l].ans=min(a[l].ans,j*t[i].c);
		}
	}
	for (ll i=m-1;i>=1;i--)
		a[i].ans=min(a[i].ans,a[i+1].ans);
	sort(a+1,a+m+1,cmp);
	for (ll i=1;i<=m;i++)
		if (a[i].ans<=C)
			printf("%lld ",a[i].ans);
		else
			printf("-1 ");
	return 0;
}

E. Star MST(dp恶臭优化+数学)

首先我们可以根据MST的性质发现这样一个性质:

与1相连的任意两边(1,x),(1,y)的边权分别为a,b, 那么(x,y)的边权>=max(a,b),我们可以对与1相连的边权进行排序--(a_1,a_2,a_3,....,a_{n-1})[其中a_1<=a_2<=a_3<=....<=a_{n-1}],则>=a_{n-1}的边有n-2条,......,>=a_{1}的边有0条,我们可以用pow解决这组有序的(a_1,a_2,a_3,....,a_{n-1})的方案数。

因此我们可以用dp[i][j]表示i条与1相连的边最大数为j的方案数,则有:

dp[i][j]=\sum_{pj=0}^{j}dp[i-1][pj]*((j-pj)!)^{-1}*(k-i+1)^{pj+(pj+1)+.....(j-1)}

 复杂度为O(M+n^2k)(其中M为数据预处理)

#include <bits/stdc++.h>
#define ll long long
#define ls p<<1
#define rs p<<1|1
#define Ma 505
#define N 1000005
#define mod 998244353
using namespace std;
ll dp[Ma][Ma];
ll mul[N],pre[N];

ll po(ll p,ll x)
{
	ll sum=1;
	while (x)
	{
		if (x&1)
			sum=sum*p%mod;
		p=p*p%mod;
		x>>=1;
	}
	return sum;
}

void pri()
{
	mul[0]=pre[0]=1;
	for (ll i=1;i<N;i++)
		mul[i]=mul[i-1]*i%mod,pre[i]=po(mul[i],mod-2);
	return;
}

int main()
{
	pri();
	ll n,m;
	cin>>n>>m;
	n--;
	for (ll i=0;i<=m;i++)
		dp[i][0]=1;
	for (ll i=1;i<=m;i++)
	{
		for (ll j=1;j<=n;j++)
		{
			for (ll k=0;k<=j;k++)
				dp[i][j]=(dp[i][j]+dp[i-1][k]*pre[j-k]%mod*po(m-i+1,(j-1)*j/2-(k-1)*k/2))%mod;
		}
	}
	printf("%lld\n",dp[m][n]*mul[n]%mod);
	return 0;
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值