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
*/