Faraway(HDU-6639)

解析一组士兵定位问题,通过分析士兵与未知目标位置的关系,利用数学和编程技巧确定可能的目标位置数量。问题涉及绝对值方程的求解和模运算,通过枚举和区域划分策略寻找解决方案。

Problem Description

n soldiers are dispatched to somewhere in Byteland. These soldiers are going to set off now, but the target location is not so clear.

Assume the target location is at (xe,ye), it is clear that xe,ye are both non-negative integers within [0,m]. For the i-th soldier, the only thing he knows is that (|xi−xe|+|yi−ye|)modki=ti.

To find the correct target location, these soldiers are working on the information they have now. Please write a program to figure out the number of possible target locations.

Input

The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.

In each test case, there are two integers n,m(1≤n≤10,1≤m≤109) in the first line, denoting the number of soldiers and the upper bound of xe,ye.

For the next n lines, each line contains four integers xi,yi,ki,ti(0≤xi,yi≤m,2≤ki≤5,0≤ti<ki), denoting what each soldier knows.

Output

For each test case, print a single line containing an integer, denoting the number of possible target locations.

Sample Input

2
2 5
1 2 4 2
3 1 2 1
2 5
1 2 4 2
1 2 4 3

Sample Output

10
0

题意:t 组数据,每组有 n 个式子 (|x[i]-x|+|y[i]-y|)%k[i]=t[i],每组数据给出这个式子的 x[i]、y[i]、k[i]、t[i],求满足这 n 个的解 {x,y} 的个数,要求 x、y 的范围为 0~m

思路:

对于式子 (|x[i]-x|+|y[i]-y|)%k[i]=t[i] 来说,由于存在绝对值,那么首先要去绝对值

那么每个点 (x[i],y[i]) 会将平面分成 4 个部分,每个部分中的距离表达式都没有绝对值符号,那么就分成了 n^2 个区域

然后枚举每个区域,计算该区域中可能的终点(x[e],y[e])的数量,由于 1<=k[i]<=5,0<=t[i]<=4,可以发现 LCM(2,3,4,5)=60,因此只需要枚举 x[e]、y[e] 模 60 的余数,然后计算有多少个点即可

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;}
LL quickPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;}
LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-10;
const int MOD = 998244353;
const int N = 1000+5;
const int dx[] = {-1,1,0,0,1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;

int a[N], b[N];
struct Node {
    int x, y, k, t;
} node[N];
bool judge(int x, int y,int n) {
    for (int i = 1; i <= n; i++)
        if ((abs(x - node[i].x) + abs(y - node[i].y)) % node[i].k != node[i].t)
            return 0;
    return 1;
}
int cal(int left, int right) {
    right -= left + 1;
    if (right < 0)
        return 0;
    return right / 60 + 1;
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int n,m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%d%d%d%d", &node[i].x, &node[i].y, &node[i].k, &node[i].t);
            a[i] = node[i].x;
            b[i] = node[i].y;
        }
        a[n+1]=m+1;
        b[n+1]=m+1;
        
        sort(a + 1, a + n + 1 + 1);
        sort(b + 1, b + n + 1 + 1);

        LL res = 0;
        
        for (int i = 0; i <= n; i++) {//分为n^2个区域
            if (a[i] < a[i + 1]) { //防止区域重复
                for (int j = 0; j <= n; j++) {//分为n^2个区域
                    if (b[j] < b[j + 1]) { //防止区域重复
                        for (int x = 0; x < 60; x++) { //枚举终点坐标x的余数
                            for (int y = 0; y < 60; y++) { //枚举终点左边y的余数
                                int ex=a[i]+x;
                                int ey=b[j]+y;
                                if (judge(ex, ey, n)) { // 统计区域中有多少余数
                                    LL ansX=cal(ex,a[i+1]);
                                    LL ansY=cal(ey,b[j+1]);
                                    res += 1LL * ansX *ansY;
                                }
                            }
                        }
                    }
                }
            }
        }
        printf("%lld\n", res);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值