题解:

题目难度:中等难度

知识点:最大公约数、数学逻辑

思想:

1.当L是无限大的时不会存在死锁的现象,说明L越大越不容易产生死锁。因此对于指定的W,R应该存在一个临界值,超过这个值就不会产生死锁。将问题转化为对于指定的W,R,找到这样一个临界值。

2.模拟读写过程(先不考虑L):

   先进行写,然后进行读,每一次写读之后,就会消耗一定的单位,如:

当R=3,W=4时:

只写1次,那么只能读1次,读之后还剩下一个可读单位,也就是现在缓冲区消耗了一个单位,写2次的时候,能够读2次,消耗2个单位,写3次的时候,能够读3次,消耗0个单位,写4次的时候,读4次,消耗1个单位,写5次的时候,读5次,消耗2个单位,我们发现这个过程一直循环,而在这个过程中,最多消耗缓冲区的单位是2。

当R=10,W=4的时:

写1次的时候无法读,写2次的时候无法读,写3次的时候读1次,消耗2个单位,写4次读1次消耗6个单位。。。。写7次的时候读2次消耗8个单位,写8次读3次消耗2个单位,进入循环,这个过程最多消耗8个单位。

3.当考虑L时:

最初可读和可写的量分别时0,L,写一次之后,可读的量是sW,可写的量是L-sW,想要继续进行读的动作,就需要L-L%W>=R,读完之后,可读可写的量分别是sW-nR,L-sW+nR。而如果想要继续进行写,必须满足L-sW+nR>=W,也就是L>=W+sW-nR,其中sW-nR就是上面那个模拟过程中消耗的缓冲区的量consume,写完之后,再进行读的动作要满足L-L%W>=(n+1)R,所以一共需要满足两个条件,L>=W+max(consume),L-L%W>=R,其中max(consume)就是上面模拟的时候找到的最大消耗单位,那么下面问题就归约为寻找W,R的最大消耗单位,其实也就是R-最大公约数(W,R),可以这样理解,每一次写读之后都会消耗一定的长度,而消耗的最大长度为length,这可以认为是处理消息队列的瓶颈,只要这个时候还能继续写读,就一定不会产生死锁,所以L的最小单位是length+W。

最大公约数

辗转相除法(又名欧几里德法)

其算法过程为: 前提:设两数为a,b设其中a 做被除数,b做除数,temp为余数
1、大数放a中、小数放b中;
2、求a/b的余数;
3、若temp=0则b为最大公约数;
4、如果temp!=0则把b的值给a、temp的值给a;
5、返回第二步;
图片说明

long long gcd(long long m,long long  n){
    if(n==0) return m;
    else return gcd(n,m%n);
}

本题完整代码

#include<iostream>
using namespace std;

long long gcd(long long a,long long  b){
    if(b==0) return a;
    else return gcd(b,a%b);
}

int main() {
    int n;
    long long l, r, w;
    cin>>n;
    while(n--) {
        cin>>l>>r>>w;
        long long  g=gcd(r,w);

        if(r+w-g>l)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}