【USACO 2021FEB G】Count the Cows
【USACO 2021FEB G】Count the Cows
by AmanoKumiko
Description
如同平常一样,Farmer John 的奶牛们分散在他的最大的草地上。草地可以看作是一个由正方形方格组成的巨大的二维方阵(想象一个巨大的棋盘)。
奶牛分布在草地上的方式相当迷人。对于每一个满足 \(x\ge 0\) 以及 \(y\ge 0\) 的方格 \((x,y)\),当对于所有整数 \(k\ge 0\),\(\left\lfloor \frac{x}{3^k}\right\rfloor\) 和 \(\left\lfloor \frac{y}{3^k}\right\rfloor\) 除以三的余数的奇偶性均相同时,有一头奶牛位于 \((x,y)\)。换言之,两个余数均为奇数(均等于 \(1\)),或均为偶数(均等于 \(0\) 或 \(2\))。
FJ 对他的草地上的某个特定区域内的奶牛数量感兴趣。他进行了 \(Q\) 个询问,每个询问由三个整数 \(x_i,y_i,d_i\) 组成。对每个询问,FJ 想要知道有多少奶牛位于 \((x_i,y_i)\) 至 \((x_i+d_i,y_i+d_i)\) 的对角线上的方格内(包括两端)。
Input
询问数\(Q\)
以下\(Q\)行,每行三个数\(d,x,y\)
Output
输出\(Q\)行,每个询问输出一行。
Sample Input
8
10 0 0
10 0 1
9 0 2
8 0 2
0 1 7
1 1 7
2 1 7
1000000000000000000 1000000000000000000 1000000000000000000
Sample Output
11
0
4
3
1
2
2
1000000000000000001
Data Constraint
1<=Q<=10000,1<=xi,yi<=1000000000000000000
Solution
研究条件,倒序枚举\(k\)
(三进制下)在最高位时,必须保证两数奇偶性相同
到下一位时,需保证前两位的和的奇偶性相同
由于最高位已经相同,那只需要保证当前位奇偶性相同
以此类推,条件转化为三进制下,\(x,y\)的每一位的奇偶性相同
可以直接数位dp
设\(f[i][ix][iy][lim]\)
表示做到第\(i\)位,低位的\(x,y\)是否进位,以及\(d\)的限制是否顶满
转移显然
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
#define S 40
int q,numd[S],numx[S],numy[S];
LL d,x,y,f[S][2][2][2];
void ch(LL v,int *A){F(i,0,38)A[i]=v%3,v/=3;}
bool check(int x,int y){return (x<0||y<0||x>2||y>2?0:x%2==y%2);}
LL dfs(int x,int ix,int iy,int lim){
if(x<0)return (ix==iy&&ix==0);
if(f[x][ix][iy][lim]!=-1)return f[x][ix][iy][lim];
LL res=0;int up=lim?2:numd[x];
F(i,0,up) F(le,0,1) F(ri,0,1)if(check(numx[x]+le-3*ix+i,numy[x]+ri-3*iy+i)){
res+=dfs(x-1,le,ri,lim|(i<numd[x]));
}
return (f[x][ix][iy][lim]=res);
}
int main(){
scanf("%d",&q);
while(q--){
scanf("%lld%lld%lld",&d,&x,&y);
memset(f,-1,sizeof(f));
ch(d,numd);ch(x,numx);ch(y,numy);
printf("%lld\n",dfs(38,0,0,0));
}
return 0;
}