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; }