Poetic word
Dhinwaji is an acclaimed poet and likes to play with words and letters. He has bought some stickers where each sticker has a lower case english letter (a-z). The letters are indexed from 1 - 26 i.e. a has index 1, b has index 2 and so on. He has ai stickers with letter i on it. He needs to create a new word having exactly nletters. Being a programmer, Dhinwaji imposed another constraint: a letter with index j can only be placed at position i in the word if i % j = 0 i.e. i should be a multiple of j. Note that everything is 1-indexed. Note also that not all the stickers need to be used.
Dhinwaji wonders what is the lexicographically smallest word he can create that follows the above constraints. Since he is too busy writing poems, you have to help him find this word. Note that it is possible that there is no valid word of nletters that can be formed.
Input
- The first line will have a number T indicating the number of test cases. T lines follow.
- The first line of each test case will have one integer, n, denoting the required length of the new word.
- The second line of each test case will have 26 space separated integers a1, a2, ..., a26
Output
- For each test case, print one line containing the lexicographically smallest word which satisfies the conditions. If no such word is possible, print "#rekt" without the quotes.
Constraints
- 1 ≤ T ≤ 5
- 1 ≤ n ≤ 200
- 0 ≤ ai ≤ n
Example
Input: 3 3 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 3 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Output: abc aacbab #rekt
Explanation
Testcase 1: There is 1 sticker with a, b and c each. "abc" is the only valid word possible
Testcase 2: Some valid words are "abcaab", "abcbaa", "ababac" etc. The lexicographically smallest among them is aacbab
Testcase 3: There are a total of 3 letters so a word with 10 letters cannot be formed
题目大意:给你26个字母每一个的个数,让你造出一个长度为n的字符串,且字符串的字典序最小
先判断不存在的情况,假如当前我有的这些字母用来跑网络流都跑不出一个答案,那肯定是不行的。如果可以的话,再不济也就是这一个字符串,也就是有结果的。
如果存在的话,我们就枚举每个位置去放,对于一个位置,枚举26个字母,然后判断是否有可行流,就假设当前这个位置放了字符,那只需判断剩下的位置,对于剩下的位置,每个位置与可以放的字母连一条边,容量为1,源点与每个字母连一条容量为这个字母的个数的边,然后剩下的位置都与汇点连一条容量为1的边,跑一遍最大流,看最终的答案是否等于剩下的位置数,如果是的话,这个位置放这个字母就是可行的。不是的话,就“回溯”
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
using namespace std;
const int maxn=1010;
const int maxm=10010;
const int inf=0x3f3f3f3f;
struct Node
{
int to;
int capa;
int next;
}edge[maxm];
int n;
int source,sink;
int cnt;
int head[maxn];
bool vis[maxn];
int dep[maxn];
int num[30];
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
return;
}
void add(int u,int v,int capa)
{
edge[cnt].to=v;
edge[cnt].capa=capa;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].to=u;
edge[cnt].capa=0;
edge[cnt].next=head[v];
head[v]=cnt++;
return;
}
bool bfs()
{
queue<int> que;
que.push(source);
memset(dep,-1,sizeof(dep));
dep[source]=0;
while(!que.empty())
{
int node=que.front();
que.pop();
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].capa>0&&dep[v]==-1)
{
dep[v]=dep[node]+1;
if(v==sink) return true;
que.push(v);
}
}
}
return dep[sink]!=-1;
}
int dfs(int node,int minn)
{
if(node==sink||minn==0)
{
return minn;
}
int r=0;
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(dep[v]==dep[node]+1&&edge[i].capa>0)
{
int tmp=dfs(v,min(edge[i].capa,minn));
if(tmp>0)
{
edge[i].capa-=tmp;
edge[i^1].capa+=tmp;
r+=tmp;
minn-=tmp;
if(!minn) break;
}
}
}
if(!r) dep[node]=-1;
return r;
}
int dinic()
{
int maxflow=0;
while(bfs())
{
maxflow+=dfs(source,inf);
}
return maxflow;
}
bool judge(int idx)
{
init();
for(int i=1;i<=26;i++)
{
for(int j=idx+1;j<=n;j++)
{
if(j%i==0)
{
add(i,j+26,1);
}
}
add(source,i,num[i]);
}
for(int i=idx+1;i<=n;i++)
{
add(i+26,sink,1);
}
return dinic()==n-idx;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int test;
scanf("%d",&test);
while(test--)
{
source=0;
sink=300;
scanf("%d",&n);
for(int i=1;i<=26;i++)
{
scanf("%d",&num[i]);
}
if(!judge(0))
{
puts("#rekt");
}
else
{
string ans="";
for(int i=1;i<=n;i++)
{
for(int j=1;j<=26;j++)
{
if(num[j]>0&&i%j==0)
{
num[j]--;
if(judge(i))
{
ans+='a'+j-1;
break;
}
num[j]++;
}
}
}
cout<<ans<<endl;
}
}
return 0;
}