P9687 Maps.题解

该博客是P9687 Maps.题解。题目要求每组数据中保证有p个白色在两黑色间,字典序最好且长度为n,有T组数据。解题先判断n奇偶性生成0和1交错序列,从后往前找前p个101组合,调整字符。还指出n一半小于p或p×2等于n时不满足要求。

P9687 Maps.题解

题目意思:

每组数据里, 0 0 0 代表白色,而 1 1 1 代表黑色,要保证正好有 p p p 个白色在两个黑色之间。要保证一定是字典序最好的,长度为 n n n,如果没有满足要求的,那么输出 − 1 -1 1,一共有 T T T 组数据!

大致思路:

我们先不来管不能满足要求的,看满足条件,我们可以先判断长度 n n n,是不是偶数,如果是那么我们可以发现第一位一定要为 0 0 0,奇数第一位就要是 1 1 1,所以我们建一个变量来算,接着我们可以先把它变成一种序列,那么就是由 0 0 0 1 1 1 交错组成的序列,根据 n n n 的奇偶性,来生成序列,因为要使字典序最小,所以我们可以从后往前看,找出前 p p p 101 101 101 组合,如果有多的,找出第一个多出的地方,记录它的编号 i i i,记录到 t t t 里,为了让它正好有 p p p 个,所以我们把前 t t t 个字符都改成字典序小的 0 0 0,输出即可,注意的是如果正好是 p p p 个,那就不要变化,最后输出,不加空格。接着就是不能满足要求的,当我发现规律是 n n n 的一半小于 p p p 时,兴奋地提交了上去,喜提 70 分
当我先要放弃时,找到了反例,那么又是奇偶性,所以只需要再加上一种可能, p × 2 p × 2 p×2 等于 n n n 时,也是 − 1 - 1 1。至于为什么造成这种情况,因为计算时如果除不尽那么会自动向下取整。

代码实现:

#include<bits/stdc++.h>
using namespace std;
long long t,a[1000001],l;
long long n,p,cnt;
int main(){
	cin>>t;
	for(int i=1;i<=t;i++){
		cin>>n>>p;
		int o=n;
		if(p*2>=n){//没有满足条件的
			cout<<-1<<endl;
		}else{
			memset(a,0,sizeof a);
			l=0;
			int k=1;//判断奇偶性的
			if(n%2==0){
				a[1]=0;
				k++;
			}
			for(int j=k;j<=n;j++){
				if(a[j-1]==0){
					a[j]=1;//10交错
				}else{
					a[j]=0;//10交错
				}
			}
			cnt=0;
			for(int j=n;j>=1;j--){
				if(j==n||j==1) continue;//防止越界
				if(a[j]==0&&a[j-1]==1&&a[j+1]==1){//看看满不满足101子串条件
					cnt++;//数量加1
					if(cnt>p){
						l=j;
						break;//直接结束
					}
				}
			}
			for(int j=1;j<=n;j++){
				if(l==0){//特判,如果没有多余
					cout<<a[j];
					continue;
				}
				if(j<=l){
					cout<<0;//输出
				}else{
					cout<<a[j];//输出
				}
			}
			cout<<endl;//换行
		}
	}
	return 0;
} 

这样,一道普及的题目就解决啦!

希望能给大家带来一些好的思路!!!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值