题目 | A | B | C | D | E | F | G | H | I | J | K | L | M | N |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Solved | ∙ \bullet ∙ | ∙ \bullet ∙ | ∙ \bullet ∙ | ♠ \spadesuit ♠ | ∙ \bullet ∙ | ♠ \spadesuit ♠ | ♠ \spadesuit ♠ | ∙ \bullet ∙ | ♠ \spadesuit ♠ |
♠ \spadesuit ♠比赛时通过; ∙ \bullet ∙:赛后通过; ⊘ \oslash ⊘ :比赛时尝试了未通过; ∘ \circ ∘:比赛时未尝试
A.Approach
这题有个坑点,首先三分算法肯定是想得到的了,主要是当一个点走完以后,另一个点在走的过程中可能还会出现小的抛物线,所以需要分两种情况讨论,详情见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
ll tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9+7;
const ll N = 2e3 + 10;
const ll M=1e7+10;
const double eps=1e-8;
struct Point{
double x,y;
Point(){
}
Point(double x, double y):x(x),y(y){
}
Point operator+(const Point &B){
return Point(x+B.x,y+B.y);}
Point operator-(const Point &B){
return Point(x-B.x,y-B.y);}
Point operator*(double k){
return Point(x*k,y*k);}
void input(){
cin>>x>>y;
}
}st1,ed1,st2,ed2;
struct Line{
Point st,ed;
double len,ang;
void input(){
st.input();ed.input();
ang=atan2(ed.y-st.y,ed.x-st.x);
}
}a,b;
double Distance(Point A,Point B){
double ans=(A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
return sqrt(ans);
}
double get_dis(double mid){
Point p1=Point(a.st.x+min(mid,a.len)*cos(a.ang),a.st.y+min(mid,a.len)*sin(a.ang));
Point p2=Point(b.st.x+min(mid,b.len)*cos(b.ang),b.st.y+min(mid,b.len)*sin(b.ang));
double ans=Distance(p1,p2);
return ans;
}
double solve(double l,double r){
for(int i=1;i<=1e2;++i){
double midl=(l*2+r)/3,midr=(l+r*2)/3;
if(get_dis(l)<get_dis(r)){
r=midr;
}
else{
l=midl;
}
}
double ans=get_dis(l);
if(ans-get_dis(r)>eps){
ans=get_dis(r);
}
return ans;
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
a.input();b.input();
double l=0,r=max(a.len=Distance(a.st,a.ed),b.len=Distance(b.st,b.ed));
printf("%.12lf\n",min(solve(0,min(a.len,b.len)),solve(min(a.len,b.len),max(a.len,b.len))));
return 0;
}
B.Baby name
一道思维题,赛内没通过可惜到裂开。要找到A字符串与B字符串的最大字典序子串开始的位置。先输出A最大字典序子串的首个字符,然后一个个和B中的最大字典序串的头一个字符比较,若大,则继续输出,若小,则输出B最大字典序子串。详见代码。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
int tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 3e5 + 10;
const int M=1e7+10;
const double eps=1e-8;
int len1,len2,pos1,pos2;
char s1[N],s2[N];
int main() {
// ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
scanf("%s %s",s1,s2);
len1=strlen(s1);
len2=strlen(s2);
char max1=0,max2=0;
for(int i=0;i<len1;i++){
if(s1[i]>max1){
max1=s1[i];
pos1=i+1;
}
else if(s1[i]==max1&&i>0&&s1[i-1]!=max1){
for(int j=1;j<=2*i-pos1+2;++j){
if(s1[pos1-1+j]==s1[i+j]) continue;
else if(s1[pos1-1+j]<s1[i+j]){
pos1=i+1;
break;
}
else break;
}
}
}
for(int i=0;i<len2;i++){
if(s2[i]>max2){
max2=s2[i];
pos2=i;
}
else if(s2[i]==max2&&i>0&&s2[i-1]!=max2){
for(int j=1;i+j<=2*i-pos2+1;++j){
if(s2[pos2+j]==s2[i+j]) continue;
else if(s2[pos2+j]<s2[i+j]){
pos2=i;
break;
}
else break;
}
}
}
printf("%c",max1);
for(int i=pos1;i<len1;i++){
if(s1[i]>=max2) printf("%c",s1[i]);
else break;
}
for(int i=pos2;i<len2;i++){
printf("%c",s2[i]);
}
return 0;
}
D. Dice
这题首先比较容易想到的是使用余数来进行计数,最后 n n n个骰子的余数总和为0就是答案。
一开始没有别的想法,暴力 d p dp dp一波,结果还是 T T T了
这道题首先的思路是,假如有两个骰子,结果余数 n u m [ ( i + j ) % m ] = n u m [ i ] ∗ n u m [ j ] num[(i+j)\%m]=num[i]*num[j] num[(i+j)%m]=num[i]∗num[j],由这个可以知道,是有关乘法的运算,面对这么庞大的数据,可以想到的是就是使用矩阵快速幂。
左边矩阵表示的是 当前 [ n u m 0 , n u m 1 , n u m 2 . . . . n u m k − 1 ] [num_0,num_1,num_2....num_{k-1}] [num0,num1,num2....numk−1],右矩阵表示的是通过新的乘法得到新的左矩阵
右矩阵:
[ a 0 a 1 a 2 a . . . a m − 1 a m − 1 a 0 a 1 a . . . a m − 2 a m − 2 a m − 1 a 0 a . . . a m − 3 a . . . a . . . a . . . a . . . a . . . a 1 a 2 a 3 a . . . a 0 ] ( a i 表示数量 ) \left[ \begin{matrix} a_0 & a_{1} & a_{2} & a_{...} & a_{m-1}\\ a_{m-1} & a_{0} & a_{1} &a_{...} &a_{m-2}\\ a_{m-2} & a_{m-1} & a_{0} &a_{...} & a_{m-3}\\ a_{...} & a_{...} & a_{...} & a_{...} &a_{...}\\ a_{1} & a_{2} & a_{3} &a_{...} &a_{0} \end{matrix} \tag{$a_i$表示数量} \right] ⎣⎢⎢⎢⎢⎡a0am−1am−2a...a1a1a0am−1a...a2a2a1a0a...a3a...a...a...a...a...am−1am−2am−3a...a0⎦⎥⎥⎥⎥⎤(ai表示数量)
详情见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
ll tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 2e4 + 1;
const int M=1e7+10;
const double eps=1e-8;
struct matrix{
ll a[210][210];
matrix(){
memset(a,0,sizeof a);
}
matrix cal(const matrix &A,int n){
matrix ans;
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
for(int k=0;k<n;++k){
ans.a[i][j]+=a[i][k]*A.a[k][j]%mod;
ans.a[i][j]%=mod;
}
}
}
return ans;
}
};
int num[200];
int n,k,m;
ll fp(ll x,ll y){
ll ans=1;
while(y){
if(y&1) ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans;
}
ll solve(){
matrix ans;
for(int i=0;i<m;++i) ans.a[i][i]=1;
matrix tmp;
for(int i=0;i<m;++i){
int pos=0;
for(int j=i;j>=0;--j) tmp.a[pos++][i]=num[j];
for(int j=m-1;;--j){
if(pos==m) break;
tmp.a[pos++][i]=num[j];
}
}
while(n){
if(n&1) ans=ans.cal(tmp,m);
tmp=tmp.cal(tmp,m);
n>>=1;
}
return ans.a[0][0];
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
while(~scanf("%d %d %d",&n,&k,&m)){
for(int i=0;i<m;++i){
num[i]=k/m;
}
k%=m;
for(int i=1;i<=k;++i) ++num[i];
num[0]=0;
ll ans=0;
for(int i=1;i<m;++i) ans+=num[i];
ans=fp(ans,n);
printf("%lld\n",solve()*fp(ans,mod-2)%mod);
}
return 0;
}
E. Enter to the best problem of this contest!
一道简单交互题,首先询问第1号点,知道距离后询问下一层的左子树节点,如果返回距离减小,则在左子树的下一层询问,若返回距离增加,则在右子树的下一层询问,若返回距离增加且返回距离为2,则答案在同层同祖先的另一侧。若返回距离为0,则找到答案。详见代码。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
int tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 1e5 + 10;
const int M=1e7+10;
const double eps=1e-8;
int n;
int query(int q){
printf("%d\n",q);
fflush(stdout);
int k;
scanf("%d",&k);
return k;
}
int main() {
// ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
scanf("%d",&n);
int temp=query(1),pos=1,ans;
if(temp==0){
printf("! 1\n");
return 0;
}
while(1){
temp--;
ans=query(pos*2);
if(ans==0){
printf("! %d\n",pos*2);
return 0;
}
else if(ans==temp) pos*=2;
else if(temp==0&&ans==2){
printf("! %d\n",pos*2+1);
return 0;
}
else pos=pos*2+1;
}
return 0;
}
F. Free restricted flights
这题是需要对每条边进行拆边,就每条边拆成
- 付费边
- 免费边,标序号 [ 1 , k ] [1,k] [1,k],表示是路途中第k个免费的边
这题还有一个大坑点,k有可能用不完,意思就是路途全程都是免费的,真坑
剩下的就是建边问题,对于后面返回原点的路径,直接建立反边从原点出发一个道理,并且当访问到一个点时已经用了 k 1 k_1 k1次免费机票,那么剩下的路径能使用的是 i ∈ [ 0 , k − k 1 ] i\in[0,k-k_1] i∈[0,k−k1]个免费机票
详情见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
ll tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 1e4 + 1;
const int M = 1e6 + 10;
const double eps = 1e-8;
struct edge {
int next, to, w;
}e1[M], e2[M];
int head1[N*15], head2[N*15], cnt1, cnt2;
void add(edge e[], int head[], int& cnt, int u, int v, int w) {
e[cnt].to = v;
e[cnt].next = head[u];
e[cnt].w = w;
head[u] = cnt++;
}
int n, m, a, b, k;
int id[N][15];
ll dis1[N*15], dis2[N*15], dis3[N*15], dis4[N*15];
bool vis[N*15];
struct node {
int v;
ll len;
bool friend operator<(const node& a, const node& b) {
return a.len > b.len;
}
node(int v, ll len) :v(v), len(len) {
}
};
void dijkstra(edge e[], int head[], int& cnt, ll dis[], int st) {
for (int i = 0; i < N * 15; ++i) dis[i] = 1e16;
dis[st] = 0;
memset(vis, false, sizeof vis);
priority_queue<node>que;
que.push(node(st, 0));
while (!que.empty()) {
node vn = que.top(); que.pop();
if (vis[vn.v]) continue;
int u = vn.v;
vis[u] = true;
dis[u] = vn.len;
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to;
if (vis[v]) continue;
que.push(node(v, vn.len + e[i].w));
}
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
memset(head1, -1, sizeof head1); memset(head2, -1, sizeof head2); cnt1 = cnt2 = 0;
rd(n), rd(m), rd(a), rd(b), rd(k);
int num = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= k; ++j) {
id[i][j] = ++num;
}
}
while (m--) {
int u, v, w; rd(u), rd(v),rd(w);
for (int j = 0; j < k; ++j) {
add(e1, head1, cnt1, id[u][j], id[v][j], w);
add(e1, head1, cnt1, id[u][j], id[v][j + 1], 0);
add(e2, head2, cnt2, id[v][j], id[u][j], w);
add(e2, head2, cnt2, id[v][j], id[u][j + 1], 0);
}
add(e1, head1, cnt1, id[u][k], id[v][k], w);
add(e2, head2, cnt2, id[v][k], id[u][k], w);
}
dijkstra(e1, head1, cnt1, dis1, id[a][0]);
dijkstra(e1, head1, cnt1, dis2, id[b][0]);
dijkstra(e2, head2, cnt2, dis3, id[a][0]);
dijkstra(e2, head2, cnt2, dis4, id[b][0]);
int pos = -1; ll ans = 1e16;
for (int i = 0; i < n; ++i) {
if (a == i || b == i) continue;
ll ans1 = 1e16, ans2 = 1e16;
for (int j1 = 0; j1 <= k; ++j1) {
for (int j2 = 0; j2 <= k - j1; ++j2) {
int v1 = id[i][j1];
int v2 = id[i][j2];
if (ans1 > dis1[v1] + dis3[v2]) {
ans1 = dis1[v1] + dis3[v2];
}
if (ans2 > dis2[v1] + dis4[v2]) {
ans2 = dis2[v1] + dis4[v2];
}
}
}
if (ans > ans1 + ans2) {
ans = ans1 + ans2;
pos = i;
}
}
if (ans == 1e16) puts(">:(");
else printf("%d %lld\n", pos, ans);
return 0;
}
G. Great dinner
这题不用管后面给出哪两个数字前后关系,只要知道有多少对就行了
首先 令 k k k是剩下的没有限制关系的成员 , a n s = A k k ans=A_{k}^{k} ans=Akk
令 k 1 k_1 k1是当前已经排好序的人员数量,则新一对的加入到队伍中的情况总数是 [ ( 1 + k 1 ) + 1 ] ∗ ( 1 + k 1 ) 2 \frac{[(1+k_1)+1]*(1+k_1)}{2} 2[(1+k1)+1]∗(1+k1)
详情见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
int tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
const int M = 1e7 + 10;
const double eps = 1e-8;
ll n, m;
ll bully[N], victim[N];
ll fac[N];
ll get(ll x) {
ll ans = 1;
if (x & 1) ans = ans * (1 + x) / 2 % mod * x % mod;
else ans = ans * x / 2 % mod * (1 + x) % mod;
return ans % mod;
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
fac[0] = 1;
for (int i = 1; i <= N; ++i) fac[i] = fac[i - 1] * i % mod;
rd(n), rd(m);
for (int i = 1; i <= m; i++) {
scanf("%lld %lld", &bully[i], &victim[i]);
}
m <<= 1;
ll ans = fac[n - m];
m >>= 1;
for (int i = 0; i < m; ++i) {
ans = ans * get(n - m * 2 + i * 2 + 1) % mod;
}
printf("%lld\n", ans);
return 0;
}
K. Katastrophic sort
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
ll tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 2e3 + 10;
const ll M = 1e7 + 10;
const double eps = 1e-8;
string s1, s2;
int check(string x, string y) {
int len1 = x.size(), len2 = y.size();
for (int i = 0; i < len1 && i < len2; ++i) {
if (x[i] != y[i]) {
if (x[i] < y[i]) return -1;
else return 1;
}
}
if (len1 == len2) return 0;
else if (len1 < len2) return -1;
else return 1;
}
int check1(string x, string y) {
int len1 = x.size(), len2 = y.size();
if (len1 != len2) {
if (len1 < len2) return -1;
else return 1;
}
for (int i = 0; i < len1 && i < len2; ++i) {
if (x[i] != y[i]) {
if (x[i] < y[i]) return -1;
else return 1;
}
}
return 0;
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> s1 >> s2;
string x = "", y = ""; int posx = 0, posy = 0;
for (int i = 0; i < s1.size(); ++i) {
if (!isalpha(s1[i])) {
posx = i;
break;
}
x += s1[i];
}
for (int i = 0; i < s2.size(); ++i) {
if (!isalpha(s2[i])) {
posy = i;
break;
}
y += s2[i];
}
int tmp = check(x, y);
if (tmp > 0) puts(">");
else if (tmp < 0) puts("<");
else {
string xx = "", yy = "";
for (int i = posx; i < s1.size(); ++i) {
xx += s1[i];
}
for (int i = posy; i < s2.size(); ++i) {
yy += s2[i];
}
int tmp = check1(xx, yy);
if (tmp > 0) puts(">");
else if (tmp < 0) puts("<");
else puts("=");
}
return 0;
}
L.Lonely day
题意:给定一个 n ∗ m n*m n∗m的矩阵。矩阵中有四种元素。
. . . : 可以通过。
X X X : 不可通过。
S S S : 起点。
E E E : 终点。
找出一种字典序最小的方法从 S S S走到 E E E。输出步数并输出这个走法,若没有解则输出 − 1 -1 −1。
有四种走法。
D D D : 向下走。
L L L : 向左走。
R R R : 向右走。
U U U : 向上走。
有两种方法可以到 . . .元素,符号 M M M表示现在所在的位置。
[ M . ] (1) \left[ \begin{matrix} M & . \\ \end{matrix} \right] \tag{1} [M.](1)
此时 M M M可以走到 . . .。
[ M X . . . . . . X . ] (2) \left[ \begin{matrix} M & X & ...... & X & . \\ \end{matrix} \right] \tag{2} [MX......X.](2)
此时 M M M可以走到 . . .。
题解:使用 B F S BFS BFS来解决最短路径的问题(因为太菜导致一开始想的时候居然使用了 D F S DFS DFS)。按照 D D D, L L L, R R R, U U U的顺序依次搜索(这样就能保证第一个解必定是字典序最小的)。并且使用两个二维前驱数组来保存搜索过的路径。这两个数组分别为 x _ p r e [ ] [ ] x\_pre[][] x_pre[][]和 y _ p r e [ ] [ ] y\_pre[][] y_pre[][],前者保存当前点的前驱点的 x x x坐标,后者保存当前点的前驱点的 y y y坐标。找到解后即可直接使用 D F S DFS DFS回溯查找路径并结束 B F S BFS BFS。
切记要使用一个布尔类型的 v i s [ ] [ ] vis[][] vis[][]输出来保证入队列的点不会被重复访问到。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int NN = 2e3 + 5;
struct Node {
int x, y;
};
int n, m, sx, sy, ex, ey, num;
int dir[4][2] = {
{
1, 0}, {
0, -1}, {
0, 1}, {
-1, 0}};
int x_pre[NN][NN], y_pre[NN][NN];
char ans[NN * 2];
char str[NN][NN];
bool vis[NN][NN];
void init() {
}
void dfs_ans(int x, int y) {
if (x == sx && y == sy) {
cout << num << endl;
for (int i = num - 1; i >= 0; i--)
cout << ans[i];
puts("");
return;
}
int xx = x_pre[x][y], yy = y_pre[x][y];
if (yy == y) {
if (xx > x)
ans[num++] = 'U';
else
ans[num++] = 'D';
} else if (xx == x) {
if (yy > y)
ans[num++] = 'L';
else
ans[num++] = 'R';
}
dfs_ans(xx, yy);
}
void bfs() {
queue<Node> q;
q.push({
sx, sy});
vis[sx][sy] = true;
while (!q.empty()) {
Node u = q.front();
q.pop();
if (u.x == ex && u.y == ey) {
dfs_ans(ex, ey);
return;
}
for (int i = 0; i < 4; i++) {
int xx = u.x, yy = u.y;
while (1) {
xx += dir[i][0];
yy += dir[i][1];
if (xx < 1 || xx > n || yy < 1 || yy > m || vis[xx][yy])
break;
if (str[xx][yy] == '.') {
vis[xx][yy] = true;
q.push({
xx, yy});
x_pre[xx][yy] = u.x;
y_pre[xx][yy] = u.y;
break;
}
}
}
}
printf("-1\n");
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
cin >> str[i][j];
if (str[i][j] == 'S') {
sx = i;
sy = j;
str[i][j] = '.';
} else if (str[i][j] == 'E') {
ex = i;
ey = j;
str[i][j] = '.';
}
}
bfs();
return 0;
}
M. Magic spells
普通的二分查找,将每个字母的下标存进vector里,查找的时候尽量往最左边查找,找不到就返回答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
template <typename T>
inline void rd(T& x)
{
ll tmp = 1; char c = getchar(); x = 0;
while (c > '9' || c < '0') {
if (c == '-')tmp = -1; c = getchar(); }
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0'; c = getchar(); }
x *= tmp;
}
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 2e3 + 10;
const ll M = 1e7 + 10;
const double eps = 1e-8;
string s;
vector<int>vec[30];
int len;
string check(string x) {
if (vec[x[0] - 'a'].empty()) return "IMPOSSIBLE";
int len1 = x.size(), pos = vec[x[0] - 'a'][0];
string ans = "";
ans += x[0];
for (int i = 1; i < len1; ++i) {
int ansn = -1;
int l = 0, r = vec[x[i] - 'a'].size() - 1;
while (l <= r) {
int mid = l + r >> 1;
if (vec[x[i] - 'a'][mid] > pos) {
r = mid - 1;
ansn = mid;
}
else l = mid + 1;
}
if (ansn == -1) return ans;
pos = vec[x[i] - 'a'][ansn];
ans += x[i];
}
return ans;
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> s;
len = s.size();
for (int i = 0; i < len; ++i) {
vec[s[i] - 'a'].push_back(i);
}
int n; rd(n);
while (n--) {
string x;
cin >> x;
cout << check(x) << endl;
}
return 0;
}