来记录一下翻车惨案/kk
A
判判判就好了(题面是真的难读)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
int n,a[1010],b[1010];
int main()
{
int T=read();
while (T--)
{
n=read();
rep(i,1,n) {a[i]=read(),b[i]=read();}
int ok=1;
rep(i,1,n)
if ((a[i]<a[i-1]) || (b[i]<b[i-1]) || (a[i]-a[i-1]<b[i]-b[i-1]) || (a[i]<b[i]))
{
ok=0;break;
}
if (ok) puts("YES");else puts("NO");
}
return 0;
}
B
最优策略是所有(geq x)的人都来做贡献,帮助那些最容易到达(x)的人。也就是将(a_i)排序后,操作区间一定是一段后缀,枚举之后check即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
#define int long long
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
int n,m,a[100100];
signed main()
{
int T=read();
while (T--)
{
n=read();m=read();
rep(i,1,n) a[i]=read();
sort(a+1,a+1+n);reverse(a+1,a+1+n);
ll sum=0;int pos=0;
rep(i,1,n)
{
if (a[i]>=m) sum+=a[i];
else {pos=i;break;}
}
if (!pos) {printf("%lld
",n);continue;}
int ans=pos-1;
rep(i,pos,n)
{
sum+=a[i];
if (sum>=i*m) ans=max(ans,i);
}
printf("%lld
",ans);
}
return 0;
}
C
显然我们希望爆炸所产生的伤害尽可能的大。也就是希望每一只怪兽都受到爆炸伤害。但是需要有一只怪兽作为“引信”,它是无法受到爆炸伤害的。
预处理出所有怪兽受到爆炸伤害后还需要打多少下,再枚举作为“引信”的怪兽即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=300000+100;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
#define int long long
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
int n,a[N],b[N],c[N];
signed main()
{
int T=read();
while (T--)
{
n=read();
rep(i,1,n) {a[i]=read();b[i]=read();}
ll sum=0,ans=1e18;
rep(i,1,n)
{
int pre=i-1;
if (!pre) pre+=n;
c[i]=max(0ll,a[i]-b[pre]);sum+=c[i];
}
rep(i,1,n) ans=min(ans,sum-c[i]+a[i]);
printf("%lld
",ans);
}
return 0;
}
D
打个(n=5)的序列看看:
加上换行
1 2 1 3 1 4 1 5
2 3 2 4 2 5
3 4 3 5
4 5
1
暴力模拟这个序列的生成过程即可:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
#define int long long
int n,a[400400];
ll L,R;
void out(ll l,ll r,ll L,ll R,int n,int id)
{
ll nowl=max(l,L),nowr=min(r,R);
if (nowl>nowr) return;
ll bas=l-1;
nowl-=bas;nowr-=bas;
rep(i,nowl,nowr)
{
int now;
if (i&1) now=id;
else now=(i>>1)+id;
printf("%lld ",now);
}
}
signed main()
{
int T=read();
while (T--)
{
n=read();
scanf("%lld%lld",&L,&R);
ll nowl,nowr=0;
rep(i,1,n-1)
{
int len=((n-i)<<1);
nowl=nowr+1;nowr=nowl+len-1;
out(nowl,nowr,L,R,len,i);
}
if (1ll*n*(n-1)+1==R) printf("1");
puts("");
}
return 0;
}
E
先给出结论:
-
对于(x,y)的最短路,它一定会经过(gcd(x,y)), 且(x o gcd(x,y))的路径上的所有数单调递减,(gcd(x,y) o y)的路径上的所有数单调递增。
-
对于一条路径上的数单调递减的路径(x o y),记通过每条边时除去的质数因子为(p_1,p_2,cdots,p_k),则(p_1,p_2,cdots,p_k)的顺序不影响结果。
再给出做法:
预处理出(D)的所有质因子,再在(O(sqrt D))的时间内找到(D)的所有因子及其质因数分解。对于每组询问(x y)拆成(x o gcd(x,y))与(gcd(x,y) o y),对于每个询问分别算出贡献即可。假设在这条路径上质因数(p_i)需要减少/增加(a_i)个,则答案为(frac{(sum a_i)!}{prod{a_i!}}).
最后给出xjb证明(以下整理自cf评论区)
记(x=prod_{i=1}^mp_i^{alpha_i}(alphageq 0),y=xp_i)则(w(x,y)=sigma_0(y)-sigma_0(x)=(alpha_1+1)(alpha_2+1)cdots(alpha_{i-1}+1)(alpha_{i+1}+1)cdots(alpha_m+1)=frac{sigma_0(x)}{alpha_i+1})
- 结论1:在路径(x o y)中,对每个质因数(p_i),不可能出现同时加上和减去这个质因数的情况。
不失一般性的,我们可以把这条路径看成(x o xp_i o x_1p_i o cdots o yp_i o y).
将其与(x o x_1 o cdots o y)进行比较。
除去开头和结尾,均有:(w(第一种方法)geq w(第二种方法)),取到等号当且仅当此时增加/减少的质数就是(p).然后又由于第一种方法还有开头和结尾的权值,所以一定没有第二种方法优。
这个结论把可能的路径情况分为了两大类,接下来只要对这两大类分类讨论即可。
- 结论2:路径(x o gcd(x,y) o y)比(y o mathrm{lcm}(x,y) o y)更优。
看起来十分显然
记(a=gcd(x,y),b=mathrm{lcm}(x,y)),则(x=ac_1,y=ac_2,b=ac_1c_2)
不妨设(c_1,c_2)均为质数。将两种方法的权值相减
由于(c_1 eq c_2)所以差值(>0),也就是第二种方法的权值和一定大于第一种。结论得证。
- 结论3:在路径上的数单调递减的路径(x o y)上,每次减少的质数的顺序不影响答案。
这个结论比较好证:无论其顺序如何,路径的权值和永远是(sigma_0(x)-sigma_0(y)).所以最后的方案数会是一个类似于组合数的东西。
由于是考场上rush出来的写的比较丑还请见谅qwq
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=100000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
#define int long long
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
map<int,vi> mp;
int n,Len;
void sieve(int n)
{
vi c,p;
int tmp=n;
for (int i=2;i*i<=n;i++)
{
if (n%i) continue;
int cnt=0;
while (n%i==0) {n/=i;cnt++;}
p.pb(i);c.pb(cnt);
}
if (n>1) {p.pb(n);c.pb(1);}
n=tmp;Len=p.size();
for (int i=1;i*i<=n;i++)
{
if (n%i) continue;
vi now;now.clear();
int x=i;now.resize(Len);
rep(j,0,Len-1)
{
if (x%p[j]) continue;
while (x%p[j]==0) {x/=p[j];now[j]++;}
}
mp[i]=now;
if (i*i!=n)
{
rep(j,0,Len-1) now[j]=c[j]-now[j];
mp[n/i]=now;
}
}
}
int calc(int x,int y)
{
int sum=0;
rep(i,0,Len-1) sum+=(mp[x][i]-mp[y][i]);
sum=fac[sum];
rep(i,0,Len-1) sum=mul(sum,invfac[mp[x][i]-mp[y][i]]);
return sum;
}
int solve(int x,int y)
{
int z=__gcd(x,y);
return mul(calc(x,z),calc(y,z));
}
signed main()
{
math_init();
n=read();
sieve(n);
int q=read();
while (q--)
{
int x=read(),y=read();
printf("%lld
",solve(x,y));
}
return 0;
}
F
一个经典的dp是记(f_{i,j})为考虑了(a)的前(i)个数,已经有了(b)的前(j)位时的方案数,转移则是直接根据(a_i)是否保留,以及(a_i)与(b_j)的大小关系进行转移。
考虑(i)相同时的所有状态,不难发现转移可以看做一个前缀加和一个后缀加(可能还会存在当(a_i=b_j)时的一个单点修改)可以直接线段树维护。具体转移可以看代码。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=500000+500;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
int C(int n,int m)
{
if ((n<m) || (n<0) || (m<0)) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n-m]);
}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
namespace Segment_Tree{
ll seg[N<<2],tag[N<<2];
void build(int id,int l,int r)
{
seg[id]=2e18;tag[id]=0;
if (l==r)
{
if (!l) seg[id]=0;
return;
}
int mid=(l+r)>>1;
build(id<<1,l,mid);build(id<<1|1,mid+1,r);
}
void pushdown(int id)
{
if (tag[id])
{
seg[id<<1]+=tag[id];seg[id<<1|1]+=tag[id];
tag[id<<1]+=tag[id];tag[id<<1|1]+=tag[id];
tag[id]=0;
}
}
void modify(int id,int l,int r,int ql,int qr,ll val)
{
if ((l>=ql) && (r<=qr))
{
seg[id]+=val;tag[id]+=val;
return;
}
int mid=(l+r)>>1;pushdown(id);
if (ql<=mid) modify(id<<1,l,mid,ql,qr,val);
if (qr>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
}
ll query(int id,int l,int r,int pos)
{
if (l==r) return seg[id];
int mid=(l+r)>>1;pushdown(id);
if (pos<=mid) return query(id<<1,l,mid,pos);
else return query(id<<1|1,mid+1,r,pos);
}
}
using namespace Segment_Tree;
int n,m,a[N],p[N],b[N];
int main()
{
n=read();
rep(i,1,n) a[i]=read();
rep(i,1,n) p[i]=read();
m=read();
rep(i,1,m) b[i]=read();b[m+1]=2e9;
build(1,0,m);
rep(i,1,n)
{
int j=lower_bound(b+1,b+1+m,a[i])-b;
if (a[i]==b[j])
{
ll x=query(1,0,m,j-1),pre=query(1,0,m,j),y=pre+min(p[i],0);
ll cost=min(x,y);
modify(1,0,m,j,j,cost-pre);
modify(1,0,m,0,j-1,p[i]);
modify(1,0,m,j+1,m,min(p[i],0));
}
else
{
modify(1,0,m,0,j-1,p[i]);
modify(1,0,m,j,m,min(p[i],0));
}
}
ll ans=query(1,0,m,m);
if (ans<=1e15) printf("YES
%lld",ans);
else printf("NO");
return 0;
}
G
套路题,可惜比赛时没时间了。
看见不能用kmp做的匹配问题就考虑FFT,定义匹配函数为(f_i=sum_{j=0}^i(s_j-t_{i-j})^2(p_{s_j}-t_{i-j})^2),把(f_i)看成是关于(t_{i-j})的函数后展开,做五遍多项式乘法即可。
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<bitset>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int N=200000+100;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
#define fir first
#define sec second
#define mkp make_pair
#define pb push_back
#define maxd 998244353
#define eps 1e-8
inline int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace My_Math{
#define N 100000
int fac[N+100],invfac[N+100];
int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
int mul(int x,int y) {return 1ll*x*y%maxd;}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=mul(ans,x);
x=mul(x,x);y>>=1;
}
return ans;
}
int getinv(int x) {return qpow(x,maxd-2);}
void math_init()
{
fac[0]=invfac[0]=1;
rep(i,1,N) fac[i]=mul(fac[i-1],i);
invfac[N]=getinv(fac[N]);
per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
}
#undef N
}
using namespace My_Math;
namespace polynomial{
struct complex{
double x,y;
complex (double _x=0.0,double _y=0.0) {x=_x;y=_y;}
};
complex operator +(complex a,complex b) {return complex(a.x+b.x,a.y+b.y);}
complex operator -(complex a,complex b) {return complex(a.x-b.x,a.y-b.y);}
complex operator *(complex a,complex b) {return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
complex operator *(complex a,int b) {return complex(a.x*b,a.y*b);}
int r[N<<2];
int calcr(int len)
{
int lim=1,cnt=0;
while (lim<len) {lim<<=1;cnt++;}
rep(i,0,lim-1)
r[i]=(r[i>>1]>>1)|((i&1)<<(cnt-1));
return lim;
}
void fft(int lim,complex *a,int typ)
{
rep(i,0,lim-1)
if (i<r[i]) swap(a[i],a[r[i]]);
for (int mid=1;mid<lim;mid<<=1)
{
complex wn=complex(cos(pi/mid),sin(pi/mid)*typ);
int len=(mid<<1);
for (int sta=0;sta<lim;sta+=len)
{
complex w=complex(1,0);
for (int j=0;j<mid;j++,w=w*wn)
{
complex x=a[j+sta],y=a[j+sta+mid]*w;
a[j+sta]=x+y;a[j+sta+mid]=x-y;
}
}
}
if (typ==-1)
rep(i,0,lim-1) a[i].x/=lim;
}
}
using namespace polynomial;
int n,m,a[N],b[N],p[30];
complex A[N<<2],B[N<<2],C[N<<2],emp=complex(0,0);
char s[N];
ll sum[N];
int main()
{
rep(i,1,26) p[i]=read();
scanf("%s",s);
n=strlen(s);
rep(i,0,n-1) a[i]=s[i]-'a'+1;
reverse(a,a+n);
scanf("%s",s);
m=strlen(s);
rep(i,0,m-1) b[i]=s[i]-'a'+1;
int lim=calcr(m<<1);
rep(i,0,n-1) A[i]=complex(a[i]*a[i]*p[a[i]]*p[a[i]],0);
rep(i,0,m-1) B[i]=complex(1,0);
fft(lim,A,1);fft(lim,B,1);
rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
rep(i,0,lim-1) A[i]=B[i]=emp;
rep(i,0,n-1) A[i]=complex(a[i]*p[a[i]]*(a[i]+p[a[i]])*(-2),0);
rep(i,0,m-1) B[i]=complex(b[i],0);
fft(lim,A,1);fft(lim,B,1);
rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
rep(i,0,lim-1) A[i]=B[i]=emp;
rep(i,0,n-1) A[i]=complex(a[i]*a[i]+a[i]*p[a[i]]*4+p[a[i]]*p[a[i]],0);
rep(i,0,m-1) B[i]=complex(b[i]*b[i],0);
fft(lim,A,1);fft(lim,B,1);
rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
rep(i,0,lim-1) A[i]=B[i]=0;
rep(i,0,n-1) A[i]=complex((a[i]+p[a[i]])*(-2),0);
rep(i,0,m-1) B[i]=complex(b[i]*b[i]*b[i],0);
fft(lim,A,1);fft(lim,B,1);
rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
rep(i,0,lim-1) A[i]=B[i]=emp;
rep(i,0,n-1) A[i]=complex(1,0);
rep(i,0,m-1) B[i]=complex(b[i]*b[i]*b[i]*b[i],0);
fft(lim,A,1);fft(lim,B,1);
rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
fft(lim,C,-1);
rep(i,n-1,m-1)
{
if (fabs(C[i].x)+0.5<1) putchar('1');
else putchar('0');
}
return 0;
}