300iq Contest 1 简要题解

咕咕咕

codeforces

A. Angle Beats

description

有一张\(n\times m\)的方阵,每个位置上标有*,+,.中的一种。你要用尽可能多的\(I\)型和\(L\)型覆盖这个方阵(均占恰好\(3\)个位置),要求\(I\)型中间那个位置必须是+,\(L\)型中间那个位置必须是*或者+,两者非中间的两个位置必须都是.

\(1 \le n, m \le 100.\)

solution

由于某种原因,这道题咕咕咕了。

B. Best Subsequence

description

给出\(n,k\)以及\(\{w_1,w_2,...,w_n\}\),你需要找出一个长度为\(k\)的子序列\(1 \le i_1 < i_2 < ... < i_k \le n\),最小化\(\max\{w_{i_1}+w_{i_2},w_{i_2}+w_{i_3},...,w_{i_{k-1}}+w_{i_k},w_{i_k}+w_{i_1}\}\)。

\(3 \le k \le n \le 2\times 10^5, 1 \le w_i \le 10^9.\)

solution

假设答案是\(mid\),那么子序列中相邻(首尾也算相邻)两个数中至少有一个不超过\(\lfloor\frac{mid}{2}\rfloor\)。

二分\(mid\),找出所有不超过\(\lfloor\frac{mid}{2}\rfloor\)的数,显然这些树构成的子序列是合法的,接着相邻两个数中至多插入一个新数,线性扫一遍统计即可。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e5+5;
int n,k,w[N],p[N];
int check(int mid){
int cnt=0,res=0;
for(int i=1;i<=n;++i)if(w[i]<=mid/2)p[++cnt]=i;
if(cnt<=1)return cnt;
for(int i=1;i<cnt;++i)
for(int j=p[i]+1;j<p[i+1];++j)
if(w[j]+max(w[p[i]],w[p[i+1]])<=mid){
++res;break;
}
for(int j=p[cnt]+1;j<=n;++j)
if(w[j]+max(w[p[cnt]],w[p[1]])<=mid)
return cnt+res+1;
for(int j=1;j<p[1];++j)
if(w[j]+max(w[p[cnt]],w[p[1]])<=mid)
return cnt+res+1;
return cnt+res;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)scanf("%d",&w[i]);
int l=2,r=2e9,res;
while(l<=r){
int mid=l+(r-l>>1);
if(check(mid)>=k)res=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",res);return 0;
}

C. Cool Pairs

description

给出两个\(n\)阶排列\(p,q\)和一个参数\(k\),要求构造两个序列\(a,b\)满足:

  • \(-n \le a_i, b_i \le n\)。
  • \(a_{p_1} \le a_{p_2} \le ... \le a_{p_n}, b_{q_1} \le b_{q_2} \le ... \le b_{q_n}\)。
  • 满足\(i<j, a_i<b_j\)的\((i,j)\)数量恰好为\(k\)。

\(1 \le n \le 3\times 10^5, 0 \le k \le \frac{n(n-1)}{2}.\)

solution

按照如下方法构造:

  • \(a_{p_i}=i-1-n\)。
  • 存在一个\(x\in[1,n]\),使\(\forall i\in[1,x), b_{q_i}=0, \forall i\in(x,n], b_{q_i}=n\)。

可以发现这样构造出来的满足\(i<j, a_i<b_j\)的\((i,j)\)数量为\(\sum_{i=1}^{x-1}(q_i-1)+y\),其中\(y\)是一个与\(b_{q_x}\)取值有关的在\([0,q_x)\)范围内的数。易证明这种构造方法可以对任意合法的\(k\)构造出解。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3e5+5;
int n,a[N],b[N],c[N];long long k;
int main(){
scanf("%d%lld",&n,&k);
for(int i=1,x;i<=n;++i)scanf("%d",&x),a[x]=i-1-n,b[i]=n;
for(int i=1,x;i<=n;++i){
scanf("%d",&x);
if(x-1<=k)b[x]=0,k-=x-1;
else{
for(int j=1;j<x;++j)c[j]=a[j];
sort(c+1,c+x);
b[x]=-c[k+1];break;
}
}
puts("Yes");
for(int i=1;i<=n;++i)printf("%d ",a[i]);puts("");
for(int i=1;i<=n;++i)printf("%d ",b[i]);puts("");
return 0;
}

D. Dates

description

在接下来的\(t\)天时间里,有\(n\)个女孩子想要和\(\text{y}\color{red}{\text{yb}}\) 约会。第\(i\)个女孩子想要在\([l_i,r_i]\)中的某一天和\(\text{y}\color{red}{\text{yb}}\)约会,且约会后\(\text{y}\color{red}{\text{yb}}\)会得到\(p_i\)的偷税值。在这里,我们保证\(l_i\le l_{i+1}, r_i \le r_{i+1}\)。\(\text{y}\color{red}{\text{yb}}\)在第\(i\)天至多和\(a_i\)个女孩子约会,他希望你能帮他求出他能够获得的最大偷税值之和。

\(1 \le n, t \le 3\times 10^5, 0 \le a_i \le n, 1 \le p_i \le 10^9.\)

solution

按照\(p_i\)从大到小依次加入区间,每次判断加入后是否仍存在完美匹配,这种做法的正确性显然。

根据\(Hall\)定理,判断是否存在完美匹配,只需要判断是否任意\(1 \le L \le R \le t\)均满足\(\sum_{i=L}^Ra_i \ge \sum[l_i \ge L][r_i \le R]\)。

然后由于保证了\(l_i\le l_{i+1}, r_i \le r_{i+1}\),因而枚举\(1 \le L \le R \le t\)可以替换为枚举\(1 \le L' \le R' \le n\)即枚举“区间的区间”。设\(b_i\in\{0,1\}\)表示第\(i\)个区间是否被选,那么需要满足的限制就变成了:\(\sum_{i=L}^Rb_i\le \sum_{i=l_L}^{r_R}a_i\)。

记\(sa_i,sb_i\)分别为\(a_i\)和\(b_i\)的前缀和,那么限制为\(sb_R-sb_{L-1}\le sa_{r_R}-sa_{l_L-1}\)即\(sb_R-sa_{r_R}\le sb_{L-1}-sa_{l_L-1}\)。再记\(c_i=sb_i-sa_{r_i},d_i=sb_{i-1}-sa_{l_i-1}\),限制为\(c_R\le d_L\)。

考虑每次加入一个区间即企图将某一个\(b_x\)由\(0\)改为\(1\),观察发现只会有\(c_{x...n}\)与\(d_{1...x}\)的大小关系会受到影响,因而维护后缀\(c_i\)的最大值和前缀\(d_i\)的最小值判断即可。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int N=3e5+5;
struct segment_tree{
ll op,arr[N],val[N<<2],tag[N<<2];
ll merge(ll x,ll y){return op?max(x,y):min(x,y);}
void build(int x,int l,int r){
if(l==r){val[x]=arr[l];return;}
tag[x]=0;int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
val[x]=merge(val[x<<1],val[x<<1|1]);
}
void init(int n,ll _op){
op=_op;build(1,1,n);
}
void modify(int x,int l,int r,int ql,int qr,ll v){
if(l>=ql&&r<=qr){val[x]+=v;tag[x]+=v;return;}
int mid=l+r>>1;
if(ql<=mid)modify(x<<1,l,mid,ql,qr,v);
if(qr>mid)modify(x<<1|1,mid+1,r,ql,qr,v);
val[x]=merge(val[x<<1],val[x<<1|1])+tag[x];
}
ll query(int x,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return val[x];
int mid=l+r>>1;
if(qr<=mid)return query(x<<1,l,mid,ql,qr)+tag[x];
if(ql>mid)return query(x<<1|1,mid+1,r,ql,qr)+tag[x];
return merge(query(x<<1,l,mid,ql,qr),query(x<<1|1,mid+1,r,ql,qr))+tag[x];
}
}T1,T2;
int n,m,p[N],id[N];ll sa[N],ans;
bool cmp(int x,int y){return p[x]>p[y];}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)scanf("%lld",&sa[i]),sa[i]+=sa[i-1];
for(int i=1,l,r;i<=n;++i){
scanf("%d%d%d",&l,&r,&p[i]);id[i]=i;
T1.arr[i]=-sa[r];T2.arr[i]=-sa[l-1];
}
T1.init(n,1);T2.init(n,0);sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;++i)
if(T1.query(1,1,n,id[i],n)<T2.query(1,1,n,1,id[i])){
T1.modify(1,1,n,id[i],n,1);
if(id[i]<n)T2.modify(1,1,n,id[i]+1,n,1);
ans+=p[id[i]];
}
printf("%lld\n",ans);return 0;
}

E. Expected Value

description

平面图上随机游走(每次等概率走一条出边),求从点\(1\)走到点\(n\)所需步数的期望模\(998244353\)。

\(2 \le n \le 3000.\)

solution

由于是平面图因此边数是\(O(n)\)的。

学习zzq的候选队论文可以得到一个\(O(nm)\)解稀疏矩阵的做法,其中\(m\)是矩阵非零元素数量。

但是由于这种做法较为复杂繁琐以致使人忍不住点击右上角,因为以下提交了一份每次选取非零位最少的列向量消元的做法,然后它过了。

有没有老鸽来证明(估计是不太行了)或证伪这玩意儿的复杂度鸭。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3005;
const int mod=998244353;
int n,m,a[N][N],cnt[N],pos[N],ans[N];
void Inc(int &x,int y){x+=y;x>=mod?x-=mod:x;}
int fastpow(int x,int y){
int res=1;
while(y){if(y&1)res=1ll*res*x%mod;x=1ll*x*x%mod;y>>=1;}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%*d%*d");
scanf("%d",&m);
for(int i=1,x,y;i<=m;++i){
scanf("%d%d",&x,&y);
Inc(a[x][x],mod-1);Inc(a[y][y],mod-1);
Inc(a[x][y],1);Inc(a[y][x],1);
Inc(a[x][n+1],1);Inc(a[y][n+1],1);
}
for(int i=1;i<=n+1;++i)a[n][i]=0;a[n][n]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=n+1;++j)
if(a[i][j])++cnt[i];
cnt[0]=1<<30;
for(int i=1;i<=n;++i){
int r=0;
for(int j=i;j<=n;++j)if(a[j][i]&&cnt[j]<cnt[r])r=j;
if(r!=i)swap(a[r],a[i]),swap(cnt[r],cnt[i]);
int inv=fastpow(a[i][i],mod-2),top=0;
for(int j=i;j<=n+1;++j){
a[i][j]=1ll*a[i][j]*inv%mod;
if(a[i][j])pos[++top]=j;
}
for(int j=i+1;j<=n;++j)
if(a[j][i]){
int t=mod-a[j][i];
for(int k=1;k<=top;++k){
if(a[j][pos[k]])--cnt[j];
a[j][pos[k]]=(a[j][pos[k]]+1ll*t*a[i][pos[k]])%mod;
if(a[j][pos[k]])++cnt[j];
}
}
}
for(int i=n;i;--i){
ans[i]=mod-a[i][n+1];
for(int j=i+1;j<=n;++j)
ans[i]=(ans[i]+1ll*(mod-ans[j])*a[i][j])%mod;
}
printf("%d\n",ans[1]);return 0;
}

F. Free Edges

description

给一张\(n\)点\(m\)条边的图,初始时每条边都是白的,你需要选择若干条边染成黑色。

每当存在某一个点只有一条白色邻边时,这条白色邻边会变成黑色。

求出最少把多少条边染成黑色后可以使所有边都变成黑色。

$1 \le n, m \le 10^5. $

solution

其实就是问至少删掉多少条边后图中不存在环。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m,fa[N],ans;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)fa[i]=i;
for(int i=1,x,y;i<=m;++i){
scanf("%d%d",&x,&y);
if(find(x)!=find(y))fa[find(x)]=find(y);
else ++ans;
}
printf("%d\n",ans);return 0;
}

G.Graph Counting

description

给定\(n\),求有多少张\(2n\)个点的图满足不存在完美匹配,且加入任意一条不在图中的边后存在完美匹配。两张图被认为不同当且仅当无法通过重标号使两张图完全一致。答案对\(998244353\)取模。

\(1 \le n \le 5\times 10^5.\)

solution

翻题解抄了个结论:

一张图满足题述条件当且仅当存在若干点与其余所有点均有连边,设这些点的数量为\(x\),将这些点全部删去后,图中剩下的部分是\(x+2\)个大小为奇数的团。

那么在枚举了\(x\)后,答案等于将\(2n-x\)拆分成\(x+2\)个奇数的方案数,也等于将\(n+1\)拆分成\(x+2\)正整数的方案数。

对所有的\(x\)的答案求和,发现就是将\(n+1\)拆分成至少\(2\)个正整数的方案数,也就是\(P(n+1)-1\)。

所以只要求拆分数就行了。使用五边形数定理可以做到\(O(n\sqrt n)\)的复杂度,由于常数较小,可以通过\(n \le 5\times 10^5\)的测试数据。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5e5+5;
const int mod=998244353;
int n,m,f[N],g[N];
void Inc(int &x,int y){x+=y;x>=mod?x-=mod:x;}
int main(){
scanf("%d",&n);++n;
f[1]=1;f[2]=2;f[3]=5;f[m=4]=7;
while(f[m]<=n)++m,f[m]=3+2*f[m-2]-f[m-4];
for(int i=g[0]=1;i<=n;++i)
for(int j=1;f[j]<=i;++j)
if((j+1>>1)&1)Inc(g[i],g[i-f[j]]);
else Inc(g[i],mod-g[i-f[j]]);
printf("%d\n",(g[n]+mod-1)%mod);
return 0;
}

H. Hall's Theorem

description

对于一张二分图,设\(A\)为二分图左侧的一个非空点集,定义\(N(A)\)表示\(A\)集合中所有点的相邻点构成的集合的并,即,二分图右侧与\(A\)中至少一个点相邻的点的集合。

定义一个\(A\)是不好的当且仅当\(|N(A)|<|A|\)。

给出\(n,k\),要求构造一张左右各\(n\)个点的二分图,满足恰有\(k\)个左侧的非空点集是不好的

\(1 \le n \le 20, 0 \le k < 2^n.\)

solution

出于某种原因,以下均讨论好的点集的数量(我们认为非不好的点集就是好的点集)。

不妨将限制加强一些:构造一个数列\(\{a_i\}\),要求\(n \ge a_1 \ge a_2 \ge ... \ge a_n \ge n\),然后对于二分图左侧的第\(i\)个点,它向二分图右侧的前\(a_i\)个点连边。

枚举一个集合\(A\)中的最小元素\(x\),那么这个集合的\(N(A)\)就等于\(a_x\),为保证集合是好的,我们要求集合的大小不能超过\(N(A)\)也即\(a_x\),那么这种构造方式下好的点集的总量就是:$$\sum_{i=1}n\sum_{j=0}{a_i-1}\binom{n-i}{j}$$

按照\(i\)从小到大的顺序贪心地构造\(a_i\)(这样甚至都不需要考虑\(a_i\)内部的偏序关系了),可以证明这种方法可以对任意合法的\(k\)构造出方案。

#include<cstdio>
#include<algorithm>
using namespace std;
int n,k,c[23][23],m,a[666],b[666];
int main(){
scanf("%d%d",&n,&k);k=(1<<n)-1-k;
for(int i=c[0][0]=1;i<n;++i)
for(int j=c[i][0]=1;j<=i;++j)
c[i][j]=c[i-1][j]+c[i-1][j-1];
for(int i=n-1;~i;--i)
for(int j=0;j<=i;++j)
if(k>=c[i][j])k-=c[i][j],a[++m]=n-i,b[m]=j+1;
else break;
printf("%d\n",m);
for(int i=1;i<=m;++i)printf("%d %d\n",a[i],b[i]);
return 0;
}

I. Interesting Graph

给一张图,满足如下性质:

对于任意的大小为\(7\)的子集\(A\),都存在两点\(a,b\in A\)以及一个点\(c \notin A\),满足所有从\(a\)到\(b\)的路径均包含点\(c\)。

For any subset \(A\) of \(7\) vertices of the graph, there are some two vertices \(a, b \in A\) and some vertex \(c \notin A\) such that all paths from \(a\) to \(b\) contain vertex \(c\).

求对这张图进行\(k(k=1,2,...,n)\)染色的方案数模\(998244353\)。

\(1 \le n, m \le 10^5.\)

solution

性质表明图中不存在大小大于等于\(7\)的连通块。

对所有连通块求出\(dp_i\)表示将该连通块划分成\(i\)个集合的方案数,这部分的复杂度不超过\(O(n\times 3^6)\),然后合并不同连通块时可以使用分治法法塔再套个多点求值发现\(6\)个点构成的本质不同的图只有一百多种,所以将\(dp\)数组相同的合并后直接暴力就好了。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N=1e5+5;
const int mod=998244353;
int inv[10],C[10],n,m,mrk[N],tot,all,ban[100],dp[7][100],scc,baz[N];
vector<int>E[N],foo[N],bar[N];
inline void Inc(int &x,int y){x+=y;x>=mod?x-=mod:x;}
inline int fastpow(int x,int y){
int res=1;
while(y){if(y&1)res=1ll*res*x%mod;x=1ll*x*x%mod;y>>=1;}
return res;
}
void dfs(int u){
mrk[u]=tot++;
for(int v:E[u]){
if(!~mrk[v])dfs(v);
ban[1<<mrk[u]|1<<mrk[v]]=1;
}
}
int main(){
scanf("%d%d",&n,&m);inv[1]=1;
for(int i=2;i<10;++i)inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),E[x].push_back(y),E[y].push_back(x);
memset(mrk,-1,sizeof(mrk));
for(int u=1;u<=n;++u)
if(!~mrk[u]){
memset(ban,0,sizeof(ban));tot=0;
dfs(u);all=(1<<tot)-1;
for(int i=1;i<=all;i<<=1)
for(int j=0;j<=all;++j)
if(j&i)
ban[j]|=ban[j^i];
memset(dp,0,sizeof(dp));dp[0][0]=1;
for(int i=0;i<tot;++i)
for(int j=0;j<=all;++j)
if(dp[i][j])
for(int s=all^j,k=s;k;k=(k-1)&s)
if(!ban[k])
Inc(dp[i+1][j|k],dp[i][j]);
vector<int>vec(tot);
for(int i=0;i<tot;++i)vec[i]=dp[i+1][all];
foo[++scc]=vec;
}
sort(foo+1,foo+scc+1);tot=0;
for(int i=1;i<=scc;++i){
if(i==1||foo[i]!=bar[tot])
bar[++tot]=foo[i];
++baz[tot];
}
for(int i=1;i<=n;++i){
C[0]=i;
for(int j=1;j<6;++j)C[j]=1ll*C[j-1]*(i-j+mod)%mod*inv[j+1]%mod;
int res=1;
for(int j=1;j<=tot;++j){
int s=0;
for(int k=0;k<bar[j].size();++k)
Inc(s,1ll*bar[j][k]*C[k]%mod);
res=1ll*res*fastpow(s,baz[j])%mod;
}
printf("%d ",res);
}
puts("");return 0;
}

J. Jealous Split

description

有一个非负整数序列\(\{a_i\}\),你要将他分成恰好\(k\)段,记\(s_i\)为第\(i\)段的和,\(m_i\)为第\(i\)段的最大值,你需要保证这种划分方案对任意\(1 \le i <k\)满足\(|s_i-s_{i+1}|\le \max(m_i,m_{i+1})\)。

\(3 \le k \le n \le 10^5, 0 \le a_i \le 5\times 10^4.\)

solution

我们定义“对序列进行一次\(val\)分段”为(从前往后,从后往前)扫一遍序列,每当权值和大于等于\(val\)就分一段。二分出最大的\(x\)满足对序列进行\(x\)分段后权值和大于等于\(x\)的段数大于等于\(k\),令其为\(mid\),假设对序列进行\(mid\)分段后序列被恰好分成了\(k\)段,且所有段并起来为\([1,n]\),那么可以证明这种划分方案在原问题下是合法的。

若不满足,则可以对序列倒着做\(mid+1\)分段,通过某种方式(这里的证明咕咕咕了)可以证明正着做\(mid\)分段与倒着做\(mid+1\)分段存在至少一个公共划分点,且满足用前者划分的一段前缀拼上后者划分的一段后缀恰好可以得到原问题的一组合法解。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int N=1e5+5;
int n,k,a[N],p1[N],t1,p2[N],t2;
int check(ll mid){
ll sum=0;int res=0;
for(int i=1;i<=n;++i){
sum+=a[i];
if(sum>=mid)++res,sum=0;
}
return res;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
ll l=0,r=5e9,res;
while(l<=r){
ll mid=l+r>>1;
if(check(mid)>=k)res=mid,l=mid+1;
else r=mid-1;
}
ll sum=0;
for(int i=1;i<=n;++i){
sum+=a[i];
if(sum>=res)p1[++t1]=i,sum=0;
}
sum=0;
for(int i=n;i;--i){
sum+=a[i];
if(sum>=res+1)p2[++t2]=i,sum=0;
}
puts("Yes");
if(t1==k&&p1[k]==n){
for(int i=1;i<k;++i)printf("%d ",p1[i]);
puts("");return 0;
}
for(int i=1;i<=t1;++i)
if(k-i>=1&&k-i<=t2&&p1[i]+1==p2[k-i]){
for(int j=1;j<=i;++j)printf("%d ",p1[j]);
for(int j=k-i-1;j;--j)printf("%d ",p2[j]-1);
puts("");return 0;
}
return 0;
}

K. Knowledge

description

有一个仅包含两种字符ab的字符串\(S\),可对其进行的操作为在任意位置插入或删除子串aabbb以及ababab。问字符串\(S\)在进行若干次操作后能够得到多少种不同的长度为\(m\)的串。

\(1 \le |S| \le 3\times 10^5, 1 \le m \le 10^9.\)

solution

实际上任意一个串都可以经过若干次操作得到一个唯一的长度最短的串,而这个串的最长长度不会超过\(4\)。

通过大力枚举可以得知这个“唯一的长度最短的串”只有\(12\)种,因此矩乘计算答案即可,复杂度为\(O(12^3\log m)\)。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int mod=998244353;
map<string,string>trans;
map<string,int>state;
string str[15];int tot,n,m;
void add(string s){str[state[s]=++tot]=s;}
int f(string s){
string t;
for(int i=0;i<s.size();++i){
t+=s[i];
if(trans.count(t))t=trans[t];
}
return state[t];
}
struct mat{
int a[15][15];
mat(){memset(a,0,sizeof(a));}
int *operator [](int x){return a[x];}
mat operator * (mat b){
mat c;
for(int i=1;i<=tot;++i)
for(int j=1;j<=tot;++j)
for(int k=1;k<=tot;++k)
c[i][k]=(c[i][k]+1ll*a[i][j]*b[j][k])%mod;
return c;
}
}S,T;
int main(){
add("");
add("a");
add("b");
trans["aa"]="";
add("ab");
add("ba");
add("bb");
add("aba");
add("abb");
trans["baa"]="b";
add("bab");
add("bba");
trans["bbb"]="";
trans["abaa"]="ab";
trans["abab"]="bba";
trans["abba"]="bab";
trans["abbb"]="a";
trans["baba"]="abb";
add("babb");
trans["bbaa"]="bb";
add("bbab");
trans["babba"]="bbab";
trans["babbb"]="ba";
trans["bbaba"]="babb";
trans["bbabb"]="aba";
for(int i=1;i<=tot;++i){
S[i][i]=1;
++T[i][f(str[i]+"a")];
++T[i][f(str[i]+"b")];
}
cin>>n>>str[0]>>m;
while(m){if(m&1)S=S*T;T=T*T;m>>=1;}
cout<<S[f("")][f(str[0])]<<endl;
return 0;
}

300iq Contest 1 简要题解的更多相关文章

  1. Comet OJ - Contest #2 简要题解

    Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...

  2. Comet OJ - Contest #2简要题解

    Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...

  3. Comet OJ - Contest #5 简要题解

    好久没更博了,还是象征性地更一次. 依然延续了简要题解的风格. 题目链接 https://cometoj.com/contest/46 题解 A. 迫真字符串 记 \(s_i\) 表示数字 \(i\) ...

  4. AtCoder Grand Contest 031 简要题解

    AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...

  5. AtCoder Grand Contest 039 简要题解

    从这里开始 比赛目录 Problem A Connection and Disconnection 简单讨论即可. Code #include <bits/stdc++.h> using ...

  6. Comet OJ Contest #13 简要题解

    C2 首先用并查集维护\(1\)的连通块,然后用另外一个并查集维护第\(i\)行中,第\(j\)列之后的第一个\(0\)的位置,就是如果当前位置是\(1\)那么它的父亲是它右边的格子,否则是它自己. ...

  7. USACO 2013 November Contest Gold 简要题解

    Problem 1. Empty Stalls 扫两遍即可. Problem 2. Line of Sight 我们发现能互相看见的一对点一定能同时看见粮仓的某一段.于是转换成有n段线段,问有多少对线 ...

  8. 2018.09.08 AtCoder Beginner Contest 109简要题解

    比赛传送门 水题大赛? 全是水题啊!!! T1 ABC333 就是判断是不是两个数都是奇数就行了. 代码: #include<bits/stdc++.h> using namespace ...

  9. 2018.09.02 Atcoder Regular Contest 102简要题解

    比赛传送门 T1 Triangular Relationship 分析之后发现有两种情况: 1. n为奇数,那么所有数都是k的倍数. 2. n为偶数,那么所有数都是k/2的倍数. 然后就可以愉快A题了 ...

随机推荐

  1. linux线程回收

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), v ...

  2. C++ OpenSSL 之三:生成CSR文件

    1.等同于使用: openssl req -new -key "key_path" -out "save_path" -subj "/emailAdd ...

  3. Kafka Manager几个指标含义

    记忆早退 Brokers Spread:看作broker使用率,如kafka集群9个broker,某topic有7个partition,则broker spread: 7 / 9 = 77% Brok ...

  4. A站(ACFun)爬虫爬取并播放、下载视频(JAVA)

    本文使用的工具有vlc+ffmpeg+phantomjs 一般视频网站的视频地址暴露的方式有两种: 1.html直接暴露 2.通过ajax异步返回. A站使用的方式是第二种.针对第一种方式,直接使用j ...

  5. python基本数据类型的时间复杂度

    1.list 内部实现是数组 2.dict 内部实现是hash函数+哈希桶.一个好的hash函数使到哈希桶中的值只有一个,若多个key hash到了同一个哈希桶中,称之为哈希冲突. 3.set 内部实 ...

  6. 用Python玩转微信

    Python玩转微信 大家每天都在用微信,有没有想过用python来控制我们的微信,不多说,直接上干货!  这个是在 itchat上做的封装  http://itchat.readthedocs.io ...

  7. npm和yarn的淘宝镜像添加

    https://www.cnblogs.com/demonrain/p/8568122.html npm config set registry https://registry.npm.taobao ...

  8. The happy secret to better work,https://www.ted.com/talks/shawn_achor_the_happy_secret_to_better_work/transcript#t-100352

    When I was seven years old and my sister was just five years old, we were playing on top of a bunk b ...

  9. Windbg的快捷键

    窗口切换 可以使用以下键盘快捷方式窗口之间进行切换. 项 效果 CTRL+TAB 调试信息窗口之间切换. 通过重复使用此密钥,你可以扫描通过的所有窗口,而不考虑是否浮动. 停靠本身,或选项卡式停靠窗口 ...

  10. 一元n次方程为什么至多有n个实根

    任意一个n次多项式都可以分解成n个一次多项式的乘积.例如,对于三次多项式来说,那就可以分成三个一次式的乘积,也就是说,三次方程最多有三个根. 需要注意的是,最少的话可能一个实根都没有,如\(f(x)= ...