第七届河南省赛 zzuoj 10402: C.机器人 (拓展欧几里得) 好题

13 篇文章 0 订阅
4 篇文章 0 订阅

10402: C.机器人

Time Limit: 2 Sec   Memory Limit: 128 MB
Submit: 49   Solved: 16
[ Submit][ Status][ Web Board]

Description

Dr. Kong 设计的机器人卡尔非常活泼,既能原地蹦,又能跳远。由于受软硬件设计所限,机器人卡尔只能定点跳远。若机器人站在(XY)位置,它可以原地蹦,但只可以在(XY),(X-Y),(-XY),(-X-Y),(YX),(Y-X),(-YX),(-Y-X)八个点跳来跳去。

现在,Dr. Kong想在机器人卡尔身上设计一个计数器,记录它蹦蹦跳跳的数字变化(ST),即,路过的位置坐标值之和。

你能帮助Dr. Kong判断机器人能否蹦蹦跳跳,拼出数字(ST)吗?

假设机器人卡尔初始站在(00)位置上。

Input

第一行:             K                表示有多少组测试数据。

接下来有K行,每行:X  Y  S  T    

1≤K≤10000   -2*10<= X , Y, S, T <= 2*109

数据之间有一个空格。

Output

对于每组测试数据,输出一行:Y或者为N,分别表示可以拼出来,不能拼出来

Sample Input

3
2 1 3 3
1 1 0 1
1 0 -2 3

Sample Output

Y
N
Y

HINT

Source

第七届河南省赛

思路:(X,Y),(X,-Y),(-X,Y),(-X,-Y),(Y,X),(Y,-X),(-Y,X),(-Y,-X)
虽然八个点,其实有用的只有四个点,其他的四个点都可以被替代,比如
(x,y)可以替代 (-x, -y) <-> -[(x, y)]
设这四个点是(x,y), (x, -y), (y, x), (y,-x)分别经过a1, a2, a3, a4次
则有
(a1+a2)x + (a3+a4)y = s; ---> Ax + By = s; (很明显的不定方程的形式) 
(a1-a2)y + (a3-a4)x = t; ---> Dy + Cx = t;
仔细观察上述式子, A+D 和 B+C 都是 偶数 
对于Ax + By = s,可以利用exgcd()求出A, B的值,同理也可以求出D,C的值
如果A,B 为等式的解,那么其余的结为: 
A = A + y/gcd(A, B)*t(其中t为任意整数)
B = B - x/gcd(A, B)*t

利用上面的式子, 枚举 A,B,C,D ,知道 满足 A+D 和 B+C的结果为偶数! 

//不理解拓展欧几里得算法的看大神博客:http://blog.csdn.net/zhjchengfeng5/article/details/7786595

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 510
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	ll d=exgcd(b,a%b,x,y);
	ll t=x;
	x=y;
	y=t-a/b*y;
	return d;
}
int main()
{
	int T,i,j;
	ll x,y,s,t;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld%lld%lld%lld",&x,&y,&s,&t);
		ll a,b,c,d,g;
		g=exgcd(x,y,a,b);
		c=a;d=b;
		if(s%g==0&&t%g==0)
		{
			a=a*(s/g);
			b=b*(s/g);
			c=c*(t/g);
			d=d*(t/g);
			int flag=0;
			for(i=-2;i<=2&&!flag;i++)
			{
				ll aa,bb;
				aa=a+x/g*i;
				bb=b-y/g*i;
				for(j=-2;j<=2&&!flag;j++)
				{
					ll cc,dd;
					cc=c+x/g*j;
					dd=d-y/g*j;
					if((aa+dd)%2==0&&(bb+cc)%2==0)
						flag=1;
				}
			}
			if(flag)
				printf("Y\n");
			else
				printf("N\n");
		}
		else
			printf("N\n");
	}
	return 0;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个可能的实现: ```javascript function dbscan(data, eps, minPts) { // 初始化每个点的标签为-1,表示未分类 var labels = new Array(data.length).fill(-1); // 初始化聚类计数器 var clusterCount = 0; // 计算每对点之间的距离 var distances = []; for (var i = 0; i < data.length; i++) { distances[i] = []; for (var j = 0; j < data.length; j++) { distances[i][j] = euclideanDistance(data[i], data[j]); } } // 标记每个点是否为核心点,以及它的邻居 var corePoints = []; var neighbors = []; for (var i = 0; i < data.length; i++) { var count = 0; var indices = []; for (var j = 0; j < data.length; j++) { if (distances[i][j] <= eps) { count++; indices.push(j); } } if (count >= minPts) { labels[i] = -2; // 标记为核心点 corePoints.push(i); neighbors[i] = indices; } } // 迭代计算聚类 for (var i = 0; i < corePoints.length; i++) { var p = corePoints[i]; if (labels[p] === -2) { // 如果p尚未被分类 clusterCount++; labels[p] = clusterCount; // 将p标记为新的聚类 expandCluster(p, neighbors[p], clusterCount, labels, distances, eps, minPts); } } return labels; } function expandCluster(p, neighbors, clusterCount, labels, distances, eps, minPts) { for (var i = 0; i < neighbors.length; i++) { var q = neighbors[i]; if (labels[q] === -2) { // 如果q是核心点且尚未被分类 labels[q] = clusterCount; // 将q加入当前聚类 expandCluster(q, neighbors[q], clusterCount, labels, distances, eps, minPts); } else if (labels[q] === -1) { // 如果q尚未被分类 labels[q] = clusterCount; // 将q加入当前聚类 } } } function euclideanDistance(a, b) { var sum = 0; for (var i = 0; i < a.length; i++) { sum += Math.pow(a[i] - b[i], 2); } return Math.sqrt(sum); } // 示例数据 var data = [ {y: 115.9057200, x: 29.1660800, label: 0}, {y: 115.9067200, x: 29.1670800, label: 0}, {y: 115.9067200, x: 29.1660800, label: 0}, {y: 115.9077200, x: 29.1670800, label: 0}, {y: 115.9087200, x: 29.1670800, label: 0}, {y: 116.0000000, x: 30.0000000, label: 1}, {y: 116.0010000, x: 30.0010000, label: 1}, {y: 116.0010000, x: 30.0000000, label: 1}, {y: 116.0020000, x: 30.0010000, label: 1}, {y: 116.0030000, x: 30.0010000, label: 1}, ]; // 聚类参数 var eps = 0.01; var minPts = 2; // 执行聚类 var labels = dbscan(data.map(d => [d.y, d.x]), eps, minPts); // 构造颜色映射 var colors = ['blue', 'red', 'green', 'orange', 'purple', 'cyan', 'magenta', 'yellow']; var colorMap = {}; for (var i = 0; i < labels.length; i++) { if (labels[i] >= 0) { if (!colorMap[labels[i]]) { colorMap[labels[i]] = colors[Object.keys(colorMap).length]; } } } // 在leaflet地图中绘制聚类图 var map = L.map('map').setView([29.1660800, 115.9057200], 15); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors', maxZoom: 18 }).addTo(map); for (var i = 0; i < data.length; i++) { var marker = L.circleMarker([data[i].y, data[i].x], { fillColor: colorMap[labels[i]], fillOpacity: 0.8, radius: 5, stroke: false }).addTo(map); } ``` 这个实现使用了一个简单的欧几里得距离计算函数,递归地扩展每个核心点的聚类,并在每个点上绘制一个由聚类标签颜色映射而来的圆形标记。根据需要,可以调整聚类参数(eps和minPts),以及颜色映射。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值