题目大意:有一个timer,每次按下按钮就会重置为v+0.5并开始倒计时(这里的计时记的是real time多一秒,这里的timer就减一秒),如果当前灯是亮的,counter++, 如果灯是关的,就把灯打开,如果timer倒计时到0,灯熄灭。
BB和DD两个人,在从0到t的时间中,每当当前的real time%a==0时,BB按下按钮b次,real time%c==0时,DD按下按钮d次(按下按钮不算时间)规定0时刻为a和d的倍数。
题解思路:在0时刻时,第一次按下按钮,timer为v+0.5,并开始倒计时。之后在0时刻按了b+d-1次,可以求出0-t时间内按下按钮的总次数:sum=t/a*b+t/c*d+b+d-1
在这之后要处理的就是当灯灭了之后重新打开的这种操作,由于t和v很大,而这个过程就是一个过程的重复,循环节的长度为lcm(a,c)也就是说我们只要处理一个循环长度内的情况,并处理最后不满一个循环的剩余就ok了。
因为每次按下按钮就要重置,只需要考虑相邻的两个按下按钮的点,假设有两个点s1,s2,这两个点的时候BB和DD中至少有1人会按下按钮,(这两个点是按下按钮中的点这个数组中相邻的两项)如果这两项的差值大于v,在s2这个点的时候灯一定是关的,就必须花费一次去把灯打开。
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
#include <vector>
#include <cstring>
const long long mod=1e9+7;
#define ll long long
using namespace std;
vector<ll>vec;
//时间从0开始到t计,当前数为a的倍数+b,为c的倍数+d,每加了v+0.5次就-1
ll gcd(ll a,ll b)
{
ll t;
while(b)
{
t = b;
b = a % b;
a = t;
}
return a;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
ll a,b,c,d;
ll v,t;
while(T--)
{
vec.clear();
cin>>a>>b>>c>>d>>v>>t;
ll lcm;
ll g=gcd(a,c);
lcm=(a*c)/g;
//cout<<lcm<<endl;
ll ans=(t/a)*b+(t/c)*d+b+d-1;
for(ll i=0;i*a<=lcm;i++)
{
vec.push_back(i*a);
}
for(ll i=0;i*c<=lcm;i++)
{
vec.push_back(i*c);
}
vector<ll>::iterator iter;
sort(vec.begin(),vec.end());
iter=unique(vec.begin(),vec.end());
//iter++;
vec.erase(iter,vec.end());
ll time=t/lcm;
ll left=t%lcm;
ll temp=0;
for(int i=1;i<vec.size();i++)
{
if(vec[i]-vec[i-1]>v)
{
temp++;
}
}
//cout<<temp<<endl;
ans-=(time*temp);
//cout<<ans<<endl;
for(int i=1;vec[i]<=left;i++)
{
//cout<<*iter<<endl;
if(vec[i]-vec[i-1]>v)
{
ans--;
}
}
cout<<ans<<endl;
}
return 0;
}