JZOJ 7237. 【USACO 2021 February Contest, Gold】Problem 3 Count the Cows

JZOJ 7237. 【USACO 2021 February Contest, Gold】Problem 3 Count the Cows

考虑 x , y x,y x,y 满足情况,当且仅当 x x x y y y​ 的三进制表示位下每一位奇偶性相同。

所以题目转化为有多少个 z z z 满足 ( x + z , y + z ) (x+z,y+z) (x+z,y+z) 满足条件,注意 0 ≤ z ≤ d 0\leq z\leq d 0zd​ 。

考虑数位 dp ,设 f i , 0 / 1 , 0 / 1 , 0 / 1 f_{i,0/1,0/1,0/1} fi,0/1,0/1,0/1 分别表示构造到第 i i i 位的 z z z , 当前 x + z , y + z x+z,y+z x+z,y+z 分别是否进位,当前是否确定 z < d z<d z<d 的方案数。

考虑转移,在 dfs 上枚举当前位选择的数转移。设上一次存的进位分别为 c k 1 , c k 2 ck1,ck2 ck1,ck2 , 当前枚举进位 j , k j,k j,k ,那么我们要判断 x + z − 3 c k 1 + j x+z-3ck1+j x+z3ck1+j y + z − 3 c k 2 + k y+z-3ck2+k y+z3ck2+k​ 是否合法。

#include<bits/stdc++.h>
using namespace std;
int q;
typedef long long ll;
ll a[50],b[50],c[50],f[50][2][2][2],g[50][2][2][2];
ll dfs(ll len,ll ck1,ll ck2,ll ck3){
   if (len==0){
   	if (ck1==0&&ck2==0)return 1;
   	else return 0;
   }
   if (f[len][ck1][ck2][ck3]!=-1)return f[len][ck1][ck2][ck3];
   ll lim=2,ans=0;
   if (ck3==1){
   	lim=c[len];
   }
   for (ll i=0;i<=lim;i++){
   	for (ll j=0;j<=1;j++){
   		for (ll k=0;k<=1;k++){
   			ll x=a[len]+i-ck1*3+j;
   			ll y=b[len]+i-ck2*3+k;
   			if (x>=0&&y>=0&&x<=2&&y<=2&&x%2==y%2){
   				if (ck3==1&&i==c[len])ans+=dfs(len-1,j,k,1);
   				else ans+=dfs(len-1,j,k,0);
   			}
   		}
   	}
   }
   f[len][ck1][ck2][ck3]=ans;
   return ans;
}
int main(){
   freopen("count.in","r",stdin);
   freopen("count.out","w",stdout);
   scanf("%d",&q);
   while (q--){
   	memset(f,-1,sizeof(f));
   	memset(g,0,sizeof(g));
   	ll x,y,d;
   	scanf("%lld%lld%lld",&d,&x,&y);
   	ll len1=0,len2=0,len3=0;
   	memset(a,0,sizeof(a));
   	memset(b,0,sizeof(b));
   	memset(c,0,sizeof(c));
   	while (d){
   		c[++len3]=d%3;
   		d/=3;
   	}
   	while (x){
   		a[++len1]=x%3;
   		x/=3;
   	}
   	while (y){
   		b[++len2]=y%3;
   		y/=3;
   	}
   	len1=40;
   	len2=40;
   	len3=40;
   	printf("%lld\n",dfs(len3,0,0,1));
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值