https://www.cnblogs.com/violet-acmer/p/9664805.html
题目大意:
BaoBao和DreamGrid玩游戏,轮流按灯的按钮,轮到BaoBao时按下b次,轮到DreamGrid时按下d次,初始时灯是灭的,每次按下按钮等都会持续亮v+0.5秒,如果按之前灯时灭的,则按下后灯会打开,如果灯是亮的,则按下后会从之灯的照明时间为v+0.5,且counter增加1,如果在v+0.5秒每没有再一次按下按钮,灯会熄灭。
给出a,b,c,d,v,t五个数,t表示游戏时长[0,t],如果当前时刻是a的倍数,则BaoBao按按钮,如果当前时刻是c的倍数,则DreamGrid按按钮,如果是Lcm(a,c)的倍数,则两个人都会按按钮。
相关变量:
counter : 计数器
a,b,c,d,v,t : 题干所给变量
题解:
我的想法是先遍历一边a的倍数,再遍历一边c的倍数,两个for( ),第一个for( )中i=a,i每次加a,第二个for( )中i=c,i每次加c。
①先除去特殊情况,当v > min(a,c)时,只需在0处将灯打开,之后在灯熄灭前肯定会按下依次min(a,c),在这种情况下灯全程都是亮的。
②如果不是特殊情况:通过两个for( )循环每次i += a 或 i += c来减少遍历次数
第一个循环for(i=a;i <= t;i += a)不考虑在这之前是否有c的影响使当前时刻灯是亮的,所以此时counter += b-1;。
第二个循环for(i=c;i <= t;i += c)需要考虑第一个循环未考虑的情况,①当前时刻可能受前一个a的影响使灯使亮的,②或受当前时刻的影响,使下一个a时刻灯是亮的。
如果情况①和情况②同时出现,则在当前时刻不需消耗一次按动使灯打开,但受当前时刻影响,紧接着的a时刻是不需要消耗一次按动打开灯的,但是第一次循环没有考虑这个情况,故counter += d+1;。
如果情况①和情况②只出现一种,则counter += d;。
如果都不出现,则counter += d-1;。
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 using namespace std; 6 #define esp 1.0e-8 7 #define INF 10e12+1 8 typedef long long ll; 9 10 ll counter; 11 ll a,b,c,d; 12 ll v,t; 13 14 void Initial() 15 { 16 scanf("%lld%lld%lld%lld",&a,&b,&c,&d); 17 scanf("%lld%lld",&v,&t); 18 counter=b+d-1;//0时刻的情况 19 } 20 bool Special() 21 { 22 ll x=(a > c ? c:a); 23 if(v >= x) 24 { 25 counter += (t/a*b+t/c*d); 26 printf("%lld ",counter); 27 return true; 28 } 29 return false; 30 } 31 bool is_exit(ll x,ll y,ll num) 32 { 33 return x%num == 0 || y%num == 0 || (y/num-x/num > 0); 34 } 35 void Process() 36 { 37 for(ll time=a;time <= t;time += a) 38 counter += b-1; 39 40 for(ll time=c;time <= t;time += c) 41 { 42 ll suf_time=(time+v <= t ? time+v:t); 43 bool flag1=is_exit(time-v,time,a);//判断[time-v,time]是否含有a的倍数 44 bool flag2=is_exit(time,suf_time,a);//判断[time,time+v]是否含有a的倍数 45 if(time%a == 0)//特判当前时刻是a,c倍数的情况 46 counter += d; 47 else if(flag1 && flag2) 48 counter += d+1; 49 else if(flag1 || flag2) 50 counter += d; 51 else 52 counter += d-1; 53 } 54 printf("%lld ",counter); 55 } 56 int main() 57 { 58 int T; 59 scanf("%d",&T); 60 while(T--) 61 { 62 Initial(); 63 if(Special()) 64 continue; 65 Process(); 66 } 67 return 0; 68 }