P10619 [ICPC2013 WF] Harvard 题解
赛时思路
枚举所有本质不同的
然后做个矩阵,
前面的几百万乘上后面
思路
把分配到 bank
然后把程序里的这些变量删了。它们固定能一次访问到。
对于剩下的程序,统计
然后搜剩下变量的分配。复杂度对了。
code
#include<stdio.h>
#define N 1111
#define int long long
int b,s,v,n,a[14],cnt[14],ans=1ll<<60,now,st[N],sz,rgt[N];char cmd[N][9];
struct node
{
int l,r,a[14][14];
inline node()
{
l=r=0;
for(int i=1;i<=v;++i)for(int j=1;j<=v;a[i][j++]=0);
}
inline node operator*(const node&kkk)const
{
if(!l)return kkk;
if(!kkk.l)return*this;
node ans;
ans.l=l;ans.r=kkk.r;
for(int i=1;i<=v;++i)for(int j=1;j<=v;++j)
ans.a[i][j]=a[i][j]+kkk.a[i][j];
++ans.a[r][kkk.l];
return ans;
}
}c;
inline node parse(int l,int r)
{
if(l==r)
{
node ans;
int aa;sscanf(cmd[l]+1,"%lld",&aa);
if(a[aa])ans.l=ans.r=aa;
return ans;
}
if(cmd[l][0]=='V')return parse(l,l)*parse(l+1,r);
if(rgt[l]^r)return parse(l,rgt[l])*parse(rgt[l]+1,r);
node a=parse(l+1,r-1),ans;
if(!a.l)return a;
int b;sscanf(cmd[l]+1,"%lld",&b);
for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a;
return ans;
}
inline void dfs1(int i)
{
if(ans<=now)return;
if(i==v+1)
{
if(c.l)++now;
if(ans>now)ans=now;
if(c.l)--now;
return;
}
if(!a[i]){dfs1(i+1);return;}
for(int j=1;j<b;++j)if(cnt[j]<s)
{
a[i]=j;++cnt[j];int lst=now;
for(int k=1;k<i;++k)if(a[k]^j)now+=c.a[k][i]+c.a[i][k];
dfs1(i+1);
--cnt[j];now=lst;
if(!cnt[j])break;
}
}
inline void dfs0(int i)
{
if(i==v+1)
{
int c0=0;
for(int i=1;i<=v;++i)c0+=!a[i];
if(c0^s)return;
c=parse(0,n-1);
dfs1(1);
return;
}
a[i]=0;dfs0(i+1);
a[i]=1;dfs0(i+1);
}
main()
{
scanf("%lld%lld",&b,&s);v=b*s;v>13&&(v=13);
if(b>1+(v-s-1)/(s+2>>1)+1)b=1+(v-s-1)/(s+2>>1)+1;
for(;(scanf("%s",cmd[n])^EOF)&&(cmd[n][0]^'a');++n);
for(int i=n-1;i>=0;--i)if(cmd[i][0]=='E')st[sz++]=i;
else if(cmd[i][0]=='R')rgt[i]=st[--sz];
dfs0(1);
for(int i=0,s=1;i<n;++i)if(cmd[i][0]=='E')s/=st[--sz];
else if(cmd[i][0]=='R'){sscanf(cmd[i]+1,"%lld",st+sz);s*=st[sz++];}
else ans+=s;
printf("%lld",ans);
}