1. 程式人生 > >CodeChef AMLEX Poetic word(網路流)

CodeChef AMLEX Poetic word(網路流)

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 n

letters. 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 n

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