丰收

https://www.51nod.com/Contest/Problem.html#contestProblemId=4863

数位 dp,考虑对于 \((x+a,y+a),a\in[0,d]\),构造 \(a\)

每一位构造的时候满足当前 \(x+a,y+a\) 这一位奇偶性相同,但是可能后面对前面有进位,于是分别开一个是否有进位即可。

\(f[pos][0/1][0/1][0/1]\) 表示当前构造到 \(a\) 的第 \(pos\) 位,前面有没有顶上界,\(x+a\) 的第 \(pos\) 位对 \(pos+1\) 位有没有进位,后面就是 \(y+a\) 同理。

#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
int f[61][2][2][2];
int d[61],X[61],Y[61],n;

int dfs(int pos,int lim,int fl1,int fl2) {
	if(!pos) {
		if(!fl1&&!fl2) return 1;
		return 0;
	}
	if(f[pos][lim][fl1][fl2]!=-1) return f[pos][lim][fl1][fl2];
	int mx=2,qwq=0; if(lim) mx=d[pos];
	for(int i=0;i<=mx;i++) {
		for(int j=0;j<=1;j++) {
			for(int k=0;k<=1;k++) {
				int x=X[pos]+i+j-3*fl1,y=Y[pos]+i+k-3*fl2;
				if(x>=0&&y>=0&&x<=2&&y<=2&&x%2==y%2) {
					if(lim&&i==d[pos]) qwq+=dfs(pos-1,1,j,k);
					else qwq+=dfs(pos-1,0,j,k);
				}
			}
		}
	}
	return f[pos][lim][fl1][fl2]=qwq;
}

signed main() {
	cin.tie(0); ios::sync_with_stdio(false);
	cin>>n;
	while(n--) {
		memset(d,0,sizeof(d));
		memset(X,0,sizeof(X));
		memset(Y,0,sizeof(Y));
		memset(f,-1,sizeof(f));
		int tot=0,x; cin>>x;
		while(x) d[++tot]=x%3,x/=3;
		tot=0; cin>>x;
		while(x) X[++tot]=x%3,x/=3;
		tot=0; cin>>x;
		while(x) Y[++tot]=x%3,x/=3;
		cout<<dfs(60,1,0,0)<<'\n';
	}
	return 0;
}
posted @ 2022-07-04 11:12  FxorG  阅读(35)  评论(0编辑  收藏  举报