# AtCoder Grand Contest 031

Atcoder

## A - Colorful Subsequence

#### description

$$s$$中本质不同子序列的个数模$$10^9+7$$。两个子序列不同当且仅当存在一种字符在两者中的出现次数不同。

$$|s|\le10^5$$

#### solution

$$\prod_{i='a'}^{'z'}(\mbox{字符}i\mbox{出现的次数}+1)-1$$

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N=1e5+5;
const int mod=1e9+7;
int n,t[26],ans=1;char s[N];
int main(){
scanf("%d",&n);scanf("%s",s+1);
for(int i=1;i<=n;++i)++t[s[i]-'a'];
for(int i=0;i<26;++i)ans=1ll*ans*(t[i]+1)%mod;
printf("%d\n",(ans+mod-1)%mod);return 0;
}

## B - Reversi

#### description

$$n,c_i\le2\times10^5$$

#### solution

$$f_i=f_{i-1}+[lst_i<i-1]f_{lst_i}$$

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N=2e5+5;
const int mod=1e9+7;
int n,f[N],lst[N];
int main(){
n=gi();f[0]=1;
for(int i=1;i<=n;++i){
int a=gi();
f[i]=f[i-1];
if(lst[a]&&lst[a]<i-1)f[i]=(f[i]+f[lst[a]])%mod;
lst[a]=i;
}
printf("%d\n",f[n]);return 0;
}

## C - Differ by 1 Bit

#### description

$$n\le 17$$

#### solution

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
#define pc(x) __builtin_popcount(x)
int n,A,B,all;
void dfs(int x,int y,int ban){
if(pc(ban^all)==1){printf("%d %d ",y,x^y);return;}
for(int i=0;i<n;++i)
if((~ban>>i&1)&&(x>>i&1))
for(int j=0;j<n;++j)
if((~ban>>j&1)&&i!=j){
dfs(1<<j,y,ban|1<<i);
dfs(x^(1<<i)^(1<<j),y^(1<<i)^(1<<j),ban|1<<i);
return;
}
}
int main(){
n=gi(),A=gi(),B=gi(),all=(1<<n)-1;
if(pc(A^B)&1)puts("YES"),dfs(A^B,A,0);
else puts("NO");
return 0;
}

## D - A Sequence of Permutations

#### description

$$n\le10^5,k\le10^9$$

#### solution

$$[f(p,q)]_{p_i}=q_i\to f(p,q)p=q\to f(p,q)=qp^{-1}$$

$a_1=p\\a_2=q\\a_3=qp^{-1}\\a_4=qp^{-1}q^{-1}\\a_5=qp^{-1}q^{-1}pq^{-1}\\a_6=qp^{-1}q^{-1}ppq^{-1}\\a_7=qp^{-1}q^{-1}pqpq^{-1}\\a_8=qp^{-1}q^{-1}pqp^{-1}qpq^{-1}$

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
#define vi vector<int>
int n,k;vi a[7];
vi readin(){
vi res(n);
for(int i=0;i<n;++i)res[i]=gi()-1;
return res;
}
void print(vi a){
for(int i=0;i<n;++i)printf("%d ",a[i]+1);
puts("");
}
vi inv(vi a){
vi res(n);
for(int i=0;i<n;++i)res[a[i]]=i;
return res;
}
vi mul(vi a,vi b){
vi res(n);
for(int i=0;i<n;++i)res[i]=a[b[i]];
return res;
}
vi fastpow(vi a,int b){
vi res(n);
for(int i=0;i<n;++i)res[i]=i;
while(b){if(b&1)res=mul(res,a);a=mul(a,a);b>>=1;}
return res;
}
int main(){
n=gi();k=gi();
vi p=readin(),q=readin();
a[1]=p;a[2]=q;
for(int i=3;i<=6;++i)a[i]=mul(a[i-1],inv(a[i-2]));
vi A=mul(mul(q,inv(p)),mul(inv(q),p)),B=fastpow(A,(k-1)/6);
print(mul(mul(B,a[(k-1)%6+1]),inv(B)));return 0;
}

## E - Snuke the Phantom Thief

#### description

$$n \le80,m\le 320,x_i,y_i,a_i\le100,v_i\le10^{15},b_i<n$$

#### solution

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
ll gi(){
ll x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
int gc(){
char ch=getchar();
while(ch<'A'||ch>'Z')ch=getchar();
return ch;
}
const int N=405;
struct edge{int to,nxt,w;ll cost;}E[N*N];
int n,m,x[N],y[N],t[N],a[N],b[N],L[N],R[N],D[N],U[N],head[N],cnt,S,T,vis[N],pe[N];
ll v[N],dis[N],ans;queue<int>Q;
void link(int u,int v,ll w){
E[++cnt]=(edge){v,head[u],1,w};head[u]=cnt;
E[++cnt]=(edge){u,head[v],0,-w};head[v]=cnt;
}
bool spfa(ll &res){
memset(dis,63,sizeof(dis));
dis[S]=0;Q.push(S);
while(!Q.empty()){
int u=Q.front();Q.pop();vis[u]=0;
for(int i=head[u],v;i;i=E[i].nxt)
if(E[i].w&&dis[v=E[i].to]>dis[u]+E[i].cost){
dis[v]=dis[u]+E[i].cost;pe[v]=i;
if(!vis[v])vis[v]=1,Q.push(v);
}
}
if(dis[T]==dis[0])return false;res+=dis[T];
for(int i=T;i!=S;i=E[pe[i]^1].to)--E[pe[i]].w,++E[pe[i]^1].w;
return true;
}
ll cal(int k){
for(int i=1;i<=k;++i)L[i]=D[i]=0,R[i]=U[i]=233;
for(int i=1;i<=m;++i)
if(b[i]<k){
if(t[i]=='L')L[b[i]+1]=a[i]+1;
if(t[i]=='R')R[k-b[i]]=a[i]-1;
if(t[i]=='D')D[b[i]+1]=a[i]+1;
if(t[i]=='U')U[k-b[i]]=a[i]-1;
}
for(int i=2;i<=k;++i)L[i]=max(L[i],L[i-1]),D[i]=max(D[i],D[i-1]);
for(int i=k-1;i;--i)R[i]=min(R[i],R[i+1]),U[i]=min(U[i],U[i+1]);
memset(head,0,sizeof(head));cnt=1;S=n+k<<1|1;T=n+k+1<<1;
for(int i=1;i<=n;++i)link(i,n+i,-v[i]-1000000000000000ll);
for(int i=1;i<=k;++i){
link(S,n+n+i,0);link(n+n+k+i,T,0);
for(int j=1;j<=n;++j){
if(L[i]<=x[j]&&x[j]<=R[i])link(n+n+i,j,0);
if(D[i]<=y[j]&&y[j]<=U[i])link(n+j,n+n+k+i,0);
}
}
ll res=0;while(spfa(res));return -res-1000000000000000ll*k;
}
int main(){
n=gi();
for(int i=1;i<=n;++i)x[i]=gi(),y[i]=gi(),v[i]=gi();
m=gi();
for(int i=1;i<=m;++i)t[i]=gc(),a[i]=gi(),b[i]=gi();
for(int i=1;i<=n;++i)ans=max(ans,cal(i));
printf("%lld\n",ans);return 0;
}

## F - Walk on Graph

#### description

$$n,m,q \le5\times10^4,3\le mod\le 10^6,2\nmid mod$$

#### solution

1、所有的边（指状态之间的连边）都是双向的。考虑一条边$$(a,b,c)$$，通过这条边可以实现$$(a,x)\to(b,2x+c)\to(a,4x+3c)\to(b,8x+7c)\to...$$，而最终一定可以回到状态$$(a,x)$$证明略显然在模意义下每个$$x$$都有唯一对应的$$2x+c$$以及唯一对应的$$\frac{x-c}{2}$$，所以走一个长度为偶数的环就能回到原状态了。

2、如果存在两条边$$(u,v,a)$$$$(u,w,b)$$，那么就有$$(u,x)\to(v,2x+a)\to(v,4x+3a)$$以及$$(u,x)\to(w,2x+b)\to(u,4x+3b)$$，也就是说状态$$(u,4x+3a)$$与状态$$(u,4x+3b)$$是等价的，即状态$$(u,x)$$与状态$$(u,x+3(a-b))$$是等价的。

#include<cstdio>
#include<algorithm>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N=1e6+5;
int n,m,q,mod,a[N],b[N],c[N],g,z,fa[N],chk[2][N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void link(int x,int y){fa[find(x)]=find(y);}
int id(int u,int x,int y){return u*6+x*2+y;}
int main(){
n=gi();m=gi();q=gi();mod=gi();
for(int i=1;i<=m;++i){
a[i]=gi(),b[i]=gi(),c[i]=gi();
g=__gcd(g,abs(c[i]-c[1]));
}
if(!g)g=mod;mod=__gcd(mod,3*g);z=c[1]%g;
for(int i=0;i<n*6;++i)fa[i]=i;
for(int i=1;i<=m;++i){
int u=a[i]-1,v=b[i]-1,w=(c[i]-z)/g%3;
for(int x=0;x<3;++x){
link(id(u,x,0),id(v,(2*x+w)%3,1));
link(id(u,x,1),id(v,(2*x+w)%3,0));
link(id(v,x,0),id(u,(2*x+w)%3,1));
link(id(v,x,1),id(u,(2*x+w)%3,0));
}
}
for(int i=0,j=z;i<mod<<1;++i,j=(j<<1)%mod)chk[i&1][j]=1;
while(q--){
int s=gi()-1,t=gi()-1,r=gi(),res=0;
for(int x=0;x<3;++x)
for(int y=0;y<2;++y)
if(find(id(t,0,0))==find(id(s,x,y)))
res|=chk[y][(r+z+(3-x)*g)%mod];
puts(res?"YES":"NO");
}
return 0;
}

0条评论