题意
给n个式子的xi,yi,ki,ti,求满足这n个式子的解{x,y}的个数。
解的范围为0~m。
式子形如:
(
∣
x
i
−
x
∣
+
∣
y
i
−
y
∣
)
m
o
d
k
i
=
t
i
.
(|x_i−x|+|y_i−y|)mod k_i=t_i.
(∣xi−x∣+∣yi−y∣)modki=ti.
n
<
=
10
,
2
<
=
k
i
<
=
5
n<=10,2<=k_i<=5
n<=10,2<=ki<=5
思路
有绝对值,首先考虑去绝对值。
把平面分成n2个区域,在每个区域内,绝对值的影响可被忽略 。
即式子变为
(
x
i
+
y
i
−
x
−
y
)
m
o
d
k
i
=
t
i
.
(x_i+y_i−x−y)mod k_i=t_i.
(xi+yi−x−y)modki=ti.
k一共只有2、3、4、5四种取值,也就是对于每组解中的x、y,最多只有
l
c
m
(
2
,
3
,
4
,
5
)
=
60
lcm(2,3,4,5)=60
lcm(2,3,4,5)=60种对k取余的结果。
故只需枚举x、y对60的余数:0~59,然后验证,若这个余数可以,就计算这个余数下的答案数量。
标程
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=15,K=60;
int Case,n,m,x,y,i,j,ca,cb,a[N],b[N];long long ans;
struct E{
int x,y,k,t;
}e[N];
inline int abs(int x){
return x>0?x:-x;
}
inline bool check(int x,int y){
for(int i = 0; i < n;i ++)
if((abs(x-e[i].x) + abs(y-e[i].y)) % e[i].k!=e[i].t)
return 0;
return 1;
}
inline int cal(int l,int r){
r -= l+1;
if(r < 0)return 0;
return r/K+1;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
ca = 1;
cb = 1;
a[ca] = b[cb] = m+1;
//保存下来每个方程
for(i = 0; i < n; i ++){
scanf("%d%d%d%d", &e[i].x, &e[i].y, &e[i].k, &e[i].t);
a[++ca] = e[i].x;
b[++cb] = e[i].y;
}
//对于每个区域求解
sort(a+1, a+ca+1);
sort(b+1, b+cb+1);
ans = 0;
//分区域,使绝对值不影响答案个数
for(i = 0; i < ca; i ++)
if(a[i] < a[i+1])//防止区域重复
for(j = 0; j < cb; j ++)
if(b[j] < b[j+1])//防止区域重复
for(x = 0; x < K; x ++) //枚举目标坐标x、y的余数
for(y = 0; y < K; y ++)
if(check(a[i]+x,b[j]+y))//如果目标满足题目的式子们(+60不影响取模结果)
ans += 1LL * cal(a[i]+x,a[i+1]) * cal(b[j]+y,b[j+1]);// 区域里有多少这个余数的答案
printf("%lld\n",ans);
}
}