Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) |
#include<stdio.h> #include<iostream> #include<string.h> #include<ctype.h> #include<math.h> #include<map> #include<set> #include<vector> #include<queue> #include<string> #include<algorithm> #include<time.h> #include<bitset> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T> inline void gmax(T &a,T b){if(b>a)a=b;} template <class T> inline void gmin(T &a,T b){if(b<a)a=b;} const int N=1e5+10,M=0,Z=1e9+7; int casenum,casei; int n,m,K; char a[N]; //以下为爆搜打表程序 char b[4000]; bool flag; map<string,int>mop; void dfs(int p,int num) { if(num>m)return; //数量太多 if(num+n-p<m)return; //数量不够 if(p==n) { flag=1; b[p]=0; puts(b); return; } for(int i=0;i<K;i++) { b[p]='A'+i;b[p+1]=0; for(int j=0;j<=p;j++) { int h=j;int t=p; while(h<t&&b[h]==b[t]){h++;t--;} if(h>=t&&++mop[b+j]==1)++num; } dfs(p+1,num);if(flag)return;b[p+1]=0; for(int j=0;j<=p;j++) { int h=j;int t=p; while(h<t&&b[h]==b[t]){h++;t--;} if(h>=t&&--mop[b+j]==0)--num; } } } void table() { while(~scanf("%d%d%d",&n,&m,&K)) { mop.clear(); flag=0; dfs(0,0); if(!flag)puts("Impossible"); } } //以下为构造程序 void solve() { printf("Case #%d:\n",casei); if(n==m) { for(int i=0;i<n;i++)printf("%c",'A'); puts(""); } else if(n<m||K==1) { puts("Impossible"); } else if(K==2) { if(n==8&&m==7)puts("AABABBAA"); else if(m<8)puts("Impossible"); else { a[0]='A';a[1]='A';a[2]='B';a[3]='A';a[4]='B';a[5]='B'; int beh=m-8; int bef=n-beh; for(int i=6;i<bef;i++)a[i]=a[i%6]; for(int i=bef;i<n;i++)a[i]=a[i-1]; if(a[bef-1]!=a[bef-2]) { int p=(bef-1)%6; if(p==0) { a[bef++]='B'; a[bef++]='A'; a[bef++]='A'; } else if(p==2) { a[bef++]='B'; } else if(p==3) { a[bef++]='A'; } else if(p==4) { a[bef++]='A'; a[bef++]='A'; } } for(int i=bef;i<n;i++)a[i]=a[i-1];a[n]=0;puts(a); } } else { if(m<3)puts("Impossible"); else { int beh=m-3; int bef=n-beh; for(int i=0;i<bef;i++)a[i]='A'+i%3; for(int i=bef;i<n;i++)a[i]=a[i-1];a[n]=0;puts(a); } } } int main() { //table(); scanf("%d",&casenum); for(casei=1;casei<=casenum;casei++) { scanf("%d%d%d",&n,&m,&K); solve(); } } /* 【trick&&吐槽】 1,对于构造的题目,其实可以一开始写个爆搜器。 可以找规律,可以打补丁,可以对拍正确性,简直不能再舒服! 2,思维不要太浅,k==2的情况没有考虑清楚就写,导致wa了1次,查错2个小时QwQ 【题意】 T(20000)组数据, 每组数据给你n,m(1<=n,m<=1e5),k(1<=k<=26)。 让你构造一个长度恰好为n的串,串中只包含前k个大写字符,使得其包含恰好m个不相同的回文串。 【类型】 构造 【分析】 1,首先我们发现,如果n==m,以"AA...AA"的形式构造即可 2,然后我们发现,如果m>n,是不可能实现的。 即:在一个长度为n个字符串中,本质不同回文串的数量不超过n。这个可以用一句话证明—— 以每个位置为结尾的回文串中,只有能延展出的最长回文串才是新的。 因为——否则这个回文串一定是关于某个位置对称的,故而不是新的。位置只有n个,所以回文串最多也是n个。 3,于是,现在就只剩下m<n了。结合打表,便可以通过规律很快得到构造方法 (1)如果k==1,显然无解 (2)如果k==2, m<8的话无解,因为我们如果能出现重复回文串,也基于至少出现8个回文串的基础上。 (然而有一点特殊,当n=8时m可以=7) 这是因为对于:AABABB,这个串无限重复,形成AABABBAABABBAABABB…… 回文串也不过只有A,B,AA,BB,ABA,BAB,ABBA,BAAB八个。 于是,在m>=8的时候,前面n-(m-8)个是AABABBAABABB…… 后面的m-8个回文串,要如何构造呢? 我们重复的这个串AABABB,长度为6,于是分6个位置为结尾时的情况作讨论—— pos1:(AABABB)A : 延展B,得到BABBAB;再延展A,得到ABABBABA;再延展A,得到AABABBABAA;后面一直延展A pos2:(AABABB)AA : 后面一直延展A pos3:(AABABB)AAB : 延展B,得到BBAABB;后面一直延展B pos4:(AABABB)AABA : 延展A,得到AABAA;后面一直延展A pos5:(AABABB)AABAB : 延展A,得到ABABA;再延展A,得到AABABAA;后面一直延展A pos6:(AABABB)AABABB : 后面一直延展B (3)如果k==3, m<3的话无解,因为如果我们能出现重复回文串,也基于至少出现3个回文串的基础上。 这是因为,我们发现ABCABCABC……这样的串,回文串的个数也只有3个,即'A','B','C',其它串长找不到对应。 于是,在m>=3的时候,前面n-(m-3)个是ABCABCABC……,使得其最多只出现3个回文串, 而之后的m-3个回文串,我们通过把最后一个字符一直扩增得到。 【时间复杂度&&优化】 O(n) 【数据】 input 8 7 2 output AABABBAA */