ZOJ 4056 Press the Button(模拟)

题意:

 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)的倍数,则两个人都会按按钮。

思路:

如果v大于等于a和b的最小值,那么可想而知,0时刻按下后灯将会是一直亮着,所以此情况答案就是b+d-1+t/a*b+t/c*d;

再考虑一般情况,我们先遍历a的倍数,不考虑c的影响,这样ans+=(b-1),再遍历c的倍数,记f1=[i-v-0.5,i]有a的倍数,f2=[i,i+v+0.5]有a的倍数,有如下情况:

  1. i%a==0,表示i既是a和c的公倍数,那么ans+=d。
  2. f1&&f2,表示i的左右边都有a的倍数,那么ans+=(d+1)。
  3. f1||f2,表示i只有一边有a的倍数,那么ans+=d。
  4. 其他情况,ans+=d-1。

这里如何快速判断某个区间是否有某个数的倍数?暴力的话肯定会浪费很多时间,所以可以通过判断l%a==0||r%a==0||r/a-l/a>0来解决。

我没看到1e12,以为没超过int,就用的int i遍历的,,TLE了很多次,还是太菜,int的上限是2e10。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=200005;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll a,b,c,d,v,t;
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
bool check(ll l,ll r)
{
    return (l%a==0||r%a==0||r/a-l/a>0);
}
int main()
{

    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        ll ans=0;
        scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&v,&t);
        if(v>=a||v>=c)
        {
            ans=b+d-1+t/a*b+t/c*d;
        }
        else
        {
            ans+=(b+d-1);//0时刻
            //  ll lcm=a/gcd(a,c)*c;
            for(ll i=a; i<=t; i+=a)
            {
                ans+=(b-1);
            }
            for(ll i=c; i<=t; i+=c)
            {
                ll lim=(i+v<=t?i+v:t);
                ll tmp=i-v;
                bool f1=check(tmp,i);
                bool f2=check(i,lim);
                if(i%a==0)
                {
                    ans+=(d);
                }
                else if(f1&&f2)
                {
                    ans+=(d+1);
                }
                else if(f1||f2)
                {
                    ans+=d;
                }
                else
                {
                    ans+=(d-1);
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dilly__dally/article/details/82769525
ZOJ