专栏文章
题解:P12607 三叉求和
P12607题解参与者 3已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mip6x3rq
- 此快照首次捕获于
- 2025/12/03 07:09 3 个月前
- 此快照最后确认于
- 2025/12/03 07:09 3 个月前
点 的点权为 ,统计每个点权相对于父节点点权的三倍多出的 的贡献,发现是 (根节点深度为 )。于是可以从低位向高位进行 dp,设 表示考虑到深度为 时,剩余路径上选择的 的和为 ,进位到这一位的值为 的方案数。每次向后一位转移,将 减去 ,进到后一位的值即为 。
注意到有用状态数远小于 ,只转移非 的 即可通过,复杂度近似 。
CPP#include <bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;++i)
#define per(i,n,k) for(int i=n;i>=k;--i)
using namespace std;
template<typename T>
inline void read(T &x){
x=0;int f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c-'0');
x*=f;
}
template<typename T,typename ...Args>
inline void read(T &x,Args &...rest){read(x);read(rest...);}
const int N=3e3+10,MOD=1e9+7;
int n,a[N*3],vis[N*3],f[2][2*N][2*N];
vector<pair<int,int> > use[2];
string s;
vector<int> tran[2][N*2];
signed main(){
read(n);
cin>>s;
reverse(s.begin(),s.end());
rep(i,1,n){
if(s[i-1]=='?') a[i]=-1;
else a[i]=s[i-1]-'0';
}
rep(i,0,2*n) if(a[1]==-1||(i%3)==(a[1]%3)){
f[1][i][i]=1,tran[1][i].push_back(i),use[1].push_back({i,i});
}
int i1=0,i2=1;
rep(i,1,n){
i1^=1;i2^=1;
for(auto p:use[i2]) f[i2][p.first][p.second]=0;
use[i2].clear();
rep(j,0,2*(n-i+2)) tran[i2][j].clear();
rep(j,0,2*(n-i+1)){
for(auto k:tran[i1][j]){
if(vis[k]) continue;vis[k]=1;
if(f[i1][j][k]==0) continue;
rep(x,0,2){
int j2=j-x;if(j2<0) break;
int num=(k/3)+j2;
if(a[i+1]!=-1&&a[i+1]%3!=num%3) continue;
(f[i2][j2][num]+=f[i1][j][k])%=MOD;
use[i2].push_back({j2,num});
tran[i2][j2].push_back(num);
}
}
for(auto k:tran[i1][j]) vis[k]=0;
}
}
printf("%d\n",f[i2][0][0]);
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...