codeforces#1159D. The minimal unique substring(打表找规律+构造)
题目链接:
https://codeforces.com/contest/1159/problem/D
题意:
构造一个长度为$n$的$01$串,最小特殊连续字串的长度为$k$
也就是,存在最小的$k$,满足,有一个长度为$k$的连续字串没有出现过两次
数据范围:
$1 \leq k \leq n \leq 100\,000$
$(k \bmod 2) = (n \bmod 2)$
分析:
典型的构造题,构造了一下午的错误题意,😰
先说结论,算出$a=\frac{n-k}{2}$,然后打印$a$个$0$,$1$个$1$,$a$个$0$,$1$个$1$,循环过去
这个结论不好推,但是我们可以打表找规律啊
打表发现$n=10,k=8$时,只有一种构造方式$0101010101$,然后再结合$k$为其它情况时的答案
ac代码:
#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const int maxn=1e5+10;
const ll mod=998244353;
int main()
{
int n,k;
cin>>n>>k;
for(int i=0,j=(n-k)/2;i<n;i++)
{
if(j) cout<<1,j--;
else cout<<0,j=(n-k)/2;
}
return 0;
}
打表代码:
#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const int maxn=10;
const int maxm=1e6+10;
const ll mod=998244353;
vector<int>ve[25];
int ma[maxn+10][maxm];
char word[30];
int main()
{
int n=10,all=(1<<10);
for(int i=0;i<all;i++)
{
//cout<<i<<endl;
memset(ma,0,sizeof(ma));
for(int j=0;j<10;j++)
if(i&(1<<(j)))word[j]='1';
else word[j]='0';
for(int st=0;st<10;st++)
{
int now=0;
for(int en=st;en<10;en++)
{
if(word[en]=='1')now=now*2+1;
else now=now*2;
ma[en-st+1][now]++;
}
}
int fla=0;
for(int k=1;k<=10;k++)
{
//cout<<"adefsre"<<endl;
if(fla)break;
for(int j=0;j<maxm;j++)
if(ma[k][j]==1)
{
ve[k].push_back(i);
fla=1;
}
}
}
for(int k=1;k<=10;k++)
{
cout<<"k="<<k<<endl;
for(int i=0;i<ve[k].size();i++)
{
int v=ve[k][i];
for(int j=0;j<10;j++)
if(v&(1<<(j)))printf("1");
else printf("0");
printf("\n");
}
}
return 0;
}

浙公网安备 33010602011771号