题解:P14256 平局(draw)
依旧验题人题解,这个题我做了将近 8h,虽然不知道有效思考时间是多少。
首先对于一个固定的局面,有简单的
记石头布剪刀分别为
先想办法以能转成数数的方法来求固定序列的答案。
考虑转成一个从左往右扫的 dp。考虑记
一个可能没那么显然的结论是如果存在
所以
注意到上面这个做法没有任何关于取
注意到上升段长度不降,那么只要记录
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
int n,a[3005],f[3][4][3005],g[3][4][3005],suf[3005];
string s;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>s;
for(int i=1;i<=n;i++) a[i]=s[i-1]-'0',suf[i]=__builtin_popcount(a[i]);
suf[n+1]=1;
for(int i=n;i;i--) suf[i]=1ll*suf[i]*suf[i+1]%mod;
int res=0;
f[0][0][0]=1;
for(int i=1;i<=n;i++){
// cout<<i-1<<'\n';
memset(g,0,sizeof(g));
for(int s=0;s<3;s++)
for(int t=!!s;t<4;t++)
for(int x=0;x<i&&(t||!x);x++){
int tmp=f[s][t][x],e2=((s+t-x)%3+2)%3;
// if(tmp) cout<<s<<' '<<t<<' '<<x<<' '<<e2<<'\n';
for(int o=0;o<3;o++)
if(a[i]>>o&1){
if(!t) g[o][1][0]=(g[o][1][0]+tmp)%mod;
else if((e2+2)%3==o) g[s][t][x+1]=(g[s][t][x+1]+tmp)%mod;
else if(e2==o) res=(res+1ll*tmp*suf[i+1])%mod,g[s][t][x]=(g[s][t][x]+tmp)%mod;
else if(x) res=(res+1ll*tmp*suf[i+1])%mod,g[s][t][x-1]=(g[s][t][x-1]+tmp)%mod;
else{
int nt=t+1;
if(nt>3) res=(res+1ll*tmp*suf[i+1])%mod,nt-=3;
g[s][nt][0]=(g[s][nt][0]+tmp)%mod;
}
}
}
memcpy(f,g,sizeof(f));
}
// cout<<n<<'\n';
for(int i=0;i<3;i++)
for(int j=1;j<4;j++)
for(int k=0;k<n;k++){
int x=j-1,y=k;
// if(f[i][j][k]) cout<<i<<' '<<j<<' '<<k<<'\n';
res=(res+1ll*f[i][j][k]*(y/3+(x%3==2&&y%3==2)))%mod;
}
cout<<res<<'\n';
return 0;
}
/*
7
7777777
*/