- 关于math函数的使用:如何使用π——使用
acos(-1)
函数求的π值 - cout«如何输出保持小数位数——
cout << fixed << setprecision(3)
- double数如何取模——
fmod(被除数,除数)
函数(没用的操作,但至少掌握一个函数)
80分代码:
一开始的思路是将输入都存起来,根据i,j去遍历,k相乘得到sum_k,$\theta$相加得到sum_$\theta$,然后使用fmod
函数取模2π,但是超时80分
$\theta$相加得到sum_$\theta$ 看似简化,其实鸟用没有,直接cos也是一样的复杂度,你还多一个取模的操作,更慢了
唯一优化的点就在于:在i->j的遍历上,如何快速一次性查询——联想前缀和(连续子串)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<pair<int,double>> op;
while(n--){
int a;
double b;
cin>>a>>b;
pair<int,double> temp = make_pair(a,b);
op.push_back(temp);
}
double sum_k,sum_th;
while(m--){
int i,j,x,y;
cin>>i>>j>>x>>y;
i-=1;j-=1;
sum_k=1;sum_th=0;
for(int idx=i;idx<=j;++idx){
pair<int,double> temp_op = op[idx];
if(temp_op.first==1){
sum_k*=temp_op.second;//记录累计K
}else{
sum_th+=temp_op.second; //记录累计r
}
}
sum_th = fmod(sum_th, 2 * acos(-1));//以为自己聪明能降时间,其实没鸟用
cout << fixed << setprecision(3)<<sum_k*x*cos(sum_th)-sum_k*y*sin(sum_th)<<" "<<sum_k*x*sin(sum_th)+sum_k*y*cos(sum_th)<<endl;
}
return 0;
}
100分(前缀和):
- 维护一个前缀和数组,存储从0到目前为止累计的缩放k与旋转角r
- 当计算从begin到end时,利用前缀和性质快速求解
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<pair<double,double>> sum;//维护一个前缀和数组,存储从0到目前为止累计的k与r
int idx=1;
sum.push_back({1,0});//小trick,在下标0处手动添加元素,后面处理时不用特殊判断处理下标0
int flag;double op;
while(n--){
cin>>flag>>op;
if(flag==1) {
sum.push_back({sum[idx-1].first*op,sum[idx-1].second});
}else{
sum.push_back({sum[idx-1].first,sum[idx-1].second+op});
}
idx++;
}
while(m--){
int begin,end,x,y;
cin>>begin>>end>>x>>y;
double k = sum[end].first/sum[begin-1].first;//当计算从begin到end时,利用前缀和性质快速求解
double r = sum[end].second-sum[begin-1].second;
cout << fixed << setprecision(3)<<k*x*cos(r)-k*y*sin(r)<<" "<<k*x*sin(r)+k*y*cos(r)<<endl;
}
return 0;
}