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;
}
这样,一道普及的题目就解决啦!
希望能给大家带来一些好的思路!!!
该博客是P9687 Maps.题解。题目要求每组数据中保证有p个白色在两黑色间,字典序最好且长度为n,有T组数据。解题先判断n奇偶性生成0和1交错序列,从后往前找前p个101组合,调整字符。还指出n一半小于p或p×2等于n时不满足要求。
1269

被折叠的 条评论
为什么被折叠?



