(Training 13)Codeforces Round #689

A. String Generation

因为是小等于 那么我们干脆使得他没有回文
直接abcabcabc这样子

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char s[4];
int main(){
	s[1]='a';
	s[2]='b';
	s[3]='c';
	int T;
	scanf("%d",&T);
	while(T--){
		int n,k;
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++){
			cout<<s[i%3+1];
		}
		cout<<endl;
	}
}

B. Find the Spruce

题意:给出一个图 问有多少个符合规则的树
首先要预处理出每一个位置他从左到右和从右到左中的‘*’最短的长度
然后暴力判断每个位置

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
const int N=510;
char g[N][N];
int n,m,sum[N][N];
int check(int x,int y){
	int res=0;
	if(g[x][y]=='*')res++;
	else return 0;
	for(int d=x+1;d<=n;d++){
		if(sum[d][y]>=(d-x)*2+1)res++;
		else break;
	}
	return res;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(sum,0,sizeof sum);
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%s",g[i]+1);
		int res=0;
		for(int i=1;i<=n;i++){
			int pre=0;
			for(int j=1;j<=m;j++){
				if(g[i][j]=='*')pre++;
				else pre=0;
				sum[i][j]=pre;
			}
			pre=0;
			for(int j=m;j>=1;j--){
				if(g[i][j]=='*'){
					pre++;
					
				}
				else pre=0;
				sum[i][j]=min(sum[i][j]-1,pre-1)*2+1;
			}
			
		}
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++){
				res+=check(i,j);
			}
		cout<<res<<endl;
	}
}

C. Random Events

题意:确定经过m个实验后排列顺序完全升序排列的可能性

思路:从后往前看先找出后缀已经排序好的位置pre
然后如果全部排好了 那么ans=1(成功的概率)
如果不是 那么prep=1(不成功的概率)
然后因为是题意思说按顺序依次判断
依次读入x p
那么如果x>=pre
ans+=prepp;
prep=prep
(1-p);
最后输出ans即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int a[N];
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
		double ans=0,prep=1;
		int pre=n+1;
		for(int i=n;i>=1;i--){
			if(a[i]==i)pre=i;
			else break;
		}
		if(pre==1)ans=1,prep=0;
		for(int i=1;i<=m;i++){
			int x;double p;
			scanf("%d%lf",&x,&p);
			if(x>=pre-1){
				ans+=p*prep;
				prep=prep*(1-p);
			} 
		}
		printf("%.6lf\n",ans);
	}
}

D - Divide and Summarize

题意:给出数组a 能进行切片操作 选择最大值和最小值
然后取他们的平均值 然后将小的往右边 大的往左边
n次询问是否能切出一段片使得 一段等于x
思路:我们可以知道给出区间以后 这些值一定是这些不会变 那么我们可以用sort进行排序后 然后dfs来进行二分 每次把切开的片放入map中
然后查询的时候直接输出即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
const int N=1e6+10;
int a[N];
LL sum[N];
map<LL,bool>mp;
int cnt = 0;
void dfs(int l,int r){
	/*++cnt;
	if(cnt>=5)return ;*/
	if(a[l]==a[r])return ;
	int mid=(a[l]+a[r])/2;
	int p=upper_bound(a+1+l,a+1+r,mid)-(a+1);
	//cout<<a[p]<<endl;
//	cout<<sum[p]-sum[l-1]<<" : "<<sum[r]-sum[p]<<endl;
	mp[sum[p]-sum[l-1]]=1;
	mp[sum[r]-sum[p]]=1;
	dfs(l,p);
	dfs(p+1,r);
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		mp.clear();
		memset(sum,0,sizeof sum);
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		sort(a+1,a+1+n);
		for(int i=1;i<=n;i++)
		sum[i]+=sum[i-1]+a[i];
		mp[sum[n]]=1;
		dfs(1,n);
		for(int i=1;i<=m;i++){
			LL x;
			scanf("%lld",&x);
			if(mp.count(x))puts("YES");
			else puts("NO");
		}
	}
}

E. Water Level

题意:
最初,冷却器中仅装有k升水。约翰决定水的数量必须始终为至少l升,但不超过r升。约翰将在办公室呆t天。他知道他的同事每天将精确使用x升水。每天开始时,他可以向冷却器中准确添加y升水,但在任何时间点,冷却器中的水量必须在[l,r]范围内。

现在,约翰想找出他是否能够将水位维持在必要的水位达t天。帮助他回答这个问题!
思路:在x>y的时候我们只需要考虑下溢问题
判断能否在t天内供水使得不低于即可
在x<=y时我们只需要考虑上溢问题
当t<=0时能供水 当出现循环时能供水 当上溢时 不能供水

#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long LL;
unordered_map<LL,bool>mp;
int main(){
	LL k,l,r,x,y,t;
	cin>>k>>l>>r>>t>>x>>y;
	if(y<x){
		if(y+k>r)t--,k-=x;
		if(k<l||(k-l)/(x-y)<t)puts("No");
		else puts("Yes");
	}
	else{
		while(1){
			LL n=(k-l)/x;
			k-=n*x;
			t-=n;
			if(t<=0){
				puts("Yes");//已经过完t天 
				break;
			}
			if(mp[k]){//循环到过这里的话 y是x的倍数会产生循环节  
				puts("Yes");
				break;
			}
			mp[k]=1;
			if(k+y<=r){
				k+=y-x;
				if(--t<=0){
					puts("Yes");
					break;
				}
			}else {
				puts("No");
				break;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值