Educational Codeforces Round 79 (Rated for Div. 2)

萌新第三次参加比赛了。。慢慢懂了一些套路。这次发挥比之前都好,比赛中做出了三道题,排名是2400多。写一下前四道题的题解:

 

A. New Year Garland(思维)

三种颜色的灯笼排列成一条直线,直线上任意邻近的灯笼颜色不同。

给出三种灯笼的数量,判断能否满足如上条件。

解:两种灯笼的数量之和小于数量最大的灯笼个数-1就可以满足条件。复杂度O(1)

代码略

 

B. Verse For Santa(前缀和)

解:第i个verse的前缀和与S比较,小于等于S的话ans=0,大于S的话减去0~i个verse中的最大值再与S比较,小于等于S的话ans=最大值的下标。复杂度O(n).

代码:

#include<iostream> 
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cstdio>
#include<cstring>
#include<string>
#define MAXN 100
#define For(x,y) for(int x=1;x<=y;x++)
using namespace std;
long long s[100005];
int main(){
	int t;
	cin>>t;
	long long n,S,maxx,ans,index;
	while(t--){
		s[0]=0;
		maxx=0;
		ans=0;
		scanf("%lld%lld",&n,&S);
		For(i,n){
			scanf("%lld",s+i);
			if(s[i]>maxx)index=i,maxx=s[i];
			s[i]+=s[i-1];
			if(s[i]<=S)ans=0;
			else if(s[i]-maxx<=S)ans=index;
		}
		cout<<ans<<endl;
	}
	return 0;
}

C. Stack of Presents(思维)

解:存储bi在a中对应的下标,遍历bi,每次取bi时,把bi+1,bi+2..中连续的出现在bi之前的数都放在最上面,这样这些数每次只需要动一下。复杂度O(m)

#include<iostream> 
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cstdio>
#include<cstring>
#include<string>
#define MAXN 100
#define For(x,y) for(int x=0;x<y;x++)
using namespace std;
int b[100005],a[100005];
int main(){
	int t;
	cin>>t;
	int n,m,now;
	int bi,bnow;
	long long sum;
	while(t--){
		scanf("%d%d",&n,&m);
		For(i,n)scanf("%d",&now),a[now]=i;
		For(i,m)scanf("%d",b+i),b[i]=a[b[i]];
		bi=0,sum=0;
		while(bi<m){
			bnow=b[bi];
			sum+=2*(bnow-bi)+1;
			bi++;
			while(bi<m&&b[bi]<bnow)sum++,bi++;
		}
		cout<<sum<<endl;
	}
	return 0;
}

D.Santa's Bot(概率+逆元)

解:

一开始往组合数的方向想没整出来,后来看大神的代码发现就是简单的概率求和.....

做出有效决定的概率=每一个礼物被选中时为有效决定的概率之和

设p[j]为想要j礼物的人数,j礼物被选中一次且有效的概率是1/n(n个孩子选第i个)*1/ki(i孩子想要的k个礼物中选这个礼物)*p[j]/n(j礼物有效的概率),可以发现1/n可以提取,ki可以求和,这样复杂度就简化到了O(NlogMOD)

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#define MAXN 1000002
#define For(x,y) for(int x=0;x<y;x++)
#define MOD 998244353 
using namespace std;
long long a[MAXN],p[MAXN];
long long inv(long long n){
	long long m=MOD-2,s=1;
	while(m){
		if(m&1)s=s*n%MOD;
		m>>=1;
		n=n*n%MOD;
	}
	return s;
}
int main(){
	ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	long long ki,n,k,now;
	cin>>n;
	memset(a,0,sizeof(a));
	memset(p,0,sizeof(p));
	For(i,n){
		cin>>k;
		ki=inv(k)%MOD;
		For(j,k){
			cin>>now;
			a[now]=(a[now]+ki)%MOD,p[now]++;
		}
	}
	long long P=0;
	For(i,MAXN)
		if(p[i])
			P=(P+a[i]*inv(n)%MOD*inv(n)%MOD*p[i]%MOD)%MOD;
	cout<<P;
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值