CCF-CSP--坐标变换(其二)

本文介绍了在CCF-CSP问题中,如何通过两次坐标变换(缩放和旋转)实现高效计算,利用前缀和优化算法将时间复杂度从O(m*n)降低到O(m+n),并通过代码示例展示了如何使用动态数组和递推关系式求解前缀和并计算最终结果。
摘要由CSDN通过智能技术生成

CCF-CSP–坐标变换(其二)

题解

  • 首先题目要求是要完成两次转变,即放缩以及旋转
  • 放缩与旋转实际上是互不干涉的,并且由于我们只需要得出最后我们所需要的伸缩长度以及旋转角度,然后根据公式计算即可
  • 也就是说我们要完成从i 到 k的操作,相当于是对两个数组T[] (象征着伸缩变化) G[] (象征着旋转角度) 进行合并即可

优化(前缀和)

  • 此题目要是使用 for循环从i到j进行计算,其时间复杂度为O(m*n) 我们只能取得80的成绩
  • 但是我们要是使用前缀和来进行计算,其时间复杂度就是O(m+n) 即我们需要n次输入数据,n次计算前缀和,m次计算并输出数据即可
  • 所谓前缀和就是使用sum数组可以很快速的查找出从i到j的数据的合并(不一定非得是相加)
  • 其计算公式为: i 到 j 合并结果为 = sum [j] - sum[i-1]
  • 求解前缀和可以用到递推关系式 sum[i] = sum[i-1] + a[i] (这样才能真正优化)
  • 对应到T[] (合并缩放)可以是 target = sum[i] / sum[j-1]

代码参考

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n, m;
	cin >> n >> m;
	//用vector来使用动态数组
	vector<double> a(n+1);
	vector<double> b(n+1);
	for (int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;
		if (x == 1)
		{
			cin >> a[i];
			b[i] = 0;
		}
		else
		{
			cin >> b[i];
			a[i] = 1;
		}
	}
	vector<double> sum1(n+2), sum2(n+2);
	sum1[0] = 1;
	sum2[0] = 0;
	//直接计算前缀和(根据递推关系式直接求解)
 	for (int i = 1; i <=n; i++)
	{
		sum1[i] = a[i] * sum1[i - 1];
		sum2[i] = b[i] + sum2[i - 1];
	}
	//根据所给公式计算m次的结果
	for (int i = 0; i < m; i++)
	{
		int start, end;
		double x, y;
		cin >> start >> end >> x >> y;
		double k = sum1[end] / sum1[start - 1];
		double theta = sum2[end] - sum2[start - 1];
		x = x * k;
		y = y * k;
		double temp = x;
		x = x * cos(theta) - y * sin(theta);
		y = temp * sin(theta) + y * cos(theta);
		printf("%.3lf %.3lf\n", x, y);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值