题意:求一天当中有百分之多少时间满足时针、分针、秒针两两所成角度不小于n度(所成角度不大于180度)
题解:第一次写直接将时间离散化处理,跑完样例才发现这样只能求得近似解(比如当n=90时答案始终有误差),因为每一段满足条件的时间段的起始时间和终止时间都不一定是1秒的整数倍。所以考虑两两时针在一次重合和下一次重合这个周期内有多少时间段满足所成角度不小于n度,用三重循环(三根针两两组合有三种组合)枚举这些时间段,计算被三种时间段都覆盖一次的子段,每次答案加上这样的子段的终止时间与起始时间之差即可。这样的枚举的精度远比离散枚举1,2,3.....秒更高。
P.S.在循环时需要剪枝(有些三元组明显无法覆盖同一段时间的可以直接跳过),否则答案能算对但会TLE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double N=12*60*60;
//speed
const double ss=6.0;
const double sm=0.1;
const double sh=0.1/12;
//relative speed
const double rsm=ss-sm;
const double rsh=ss-sh;
const double rmh=sm-sh;
//relative period of 360
const double tsm=360.0/rsm;
const double tsh=360.0/rsh;
const double tmh=360.0/rmh;
double D;
inline double Abs(double x) {
return x>0?x:-x;
}
int main() {
// freopen("in.txt","r",stdin);
while (scanf("%lf",&D)&&(D!=-1)) {
double tot=0;
//relative period of D
double dsm=D/rsm;
double dsh=D/rsh;
double dmh=D/rmh;
//relative period of 360-D
double csm=(360.0-D)/rsm;
double csh=(360.0-D)/rsh;
double cmh=(360.0-D)/rmh;
for (double i=0;i<N;i+=tsh)
for (double j=0;j<N;j+=tsm) {
if (i+csh<j+dsm) break;
if (j+csm<i+dsh) continue;
for (double k=0;k<N;k+=tmh) {
if (j+csm<k+dmh) break;
if (k+cmh<j+dsm) continue;
double a=max(max(i+dsh,j+dsm),k+dmh);
double b=min(min(i+csh,j+csm),k+cmh);
if (a<b) tot+=b-a;
}
}
printf("%.3lf\n",tot*100/N);
}
return 0;
}