题解:P3788 幽幽子吃西瓜
lailai0916 · · 题解
解题思路
这是一道初中数学题。
由于只考虑比例,不妨设每个截面半圆的面积为
设
其中代码中需要将角度转为弧度。
考虑一个半圆内的情况,即
定义函数 sum 和 red 的贡献。
若
若
否则红色被绿色瓜皮挡住,贡献为
若
红色面积为:
于是得到核心函数:
void f(int a,int b)
{
if(a<=b)
{
sum+=s(min(max(a,180-b),90));
if(a<180-b)red+=s(b)-s(a);
}
else
{
sum+=s(min(min(a,180-b),90));
red+=s(b);
}
}
接下来只需要把整圆按
对称到前半圆处理。
若某个半圆没有被切到,则它完整可见,直接给 sum 加
最后答案为:
参考代码
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
double s(int x){return sin(x*pi/180);}
double sum=0,red=0;
void f(int a,int b)
{
if(a<=b)
{
sum+=s(min(max(a,180-b),90));
if(a<180-b)red+=s(b)-s(a);
}
else
{
sum+=s(min(min(a,180-b),90));
red+=s(b);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
while(T--)
{
int a,b;
cin>>a>>b;
sum=red=0;
if(a<b)
{
if(a<180&&b<180){f(a,b);sum+=1;}
else if(a<180&&b>=180){f(a,180);f(360-b,180);}
else if(a>=180&&b>=180){f(360-b,360-a);sum+=1;}
}
else
{
if(a<180&&b<180)f(a,b);
if(a>=180&&b<180){f(0,b);f(0,360-a);}
else if(a>=180&&b>=180)f(360-b,360-a);
}
cout<<fixed<<setprecision(1)<<red*100/sum<<'%'<<'\n';
}
return 0;
}