“玲珑杯”线上赛 Round #17 河南专场 A: Sin your life(和化积公式)

传送门

题意

分析

首先将sin(x)+sin(y)+sin(z)h转化成(2*sin(frac{x+y}2)*cos(frac{x-y}2)+sin(z)),而cos(z)=cos(-z)
1.x+y为偶数,那么x-y为偶数,且如果x+y=i,那么x-y可取的值为0,2...,i-2
2.x+y为奇数,那么x-y为奇数,切如果x+y=i,那么x-y可取的值为1,3...,i-2
那么在x+y为偶数的时候,直接取x-y为0;在x+y为奇数的时候,设一个mxodd记录从1到i-2的cos的最大值。
从0到n-1扫一遍,遇到奇数更新,并计算max值,遇到偶数直接计算max值,复杂度(O(n))

trick

代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
//#pragma comment(linker, "/STACK:102400000,102400000")
inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}
const double pi = acos(-1.0);
//double d[3003000];
int n;
double mxodd;
int main()
{
	//d[3]=cos(0.5);
	//for(int i=5;i<=3000000;i+=2) d[i]=max(d[i-2],cos((i-2)*1.0/2));
    while(scanf("%d",&n)==1)
    {
    	double ans=0,mxodd=-1e9;
    	for(int i=2;i<=n-1;++i)
    	{
    		if(i&1)
    		{
    			mxodd=max(mxodd,cos((i-2)/2));
    		 	ans=max(ans,2*sin(i*0.5)*mxodd+sin(n-i));
    		}
    		else ans=max(ans,2*sin(i*0.5)+sin(n-i));
    	}
    	printf("%.9f
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chendl111/p/7073939.html