#3144. 「APIO 2019」奇怪装置

Posted hchhch233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#3144. 「APIO 2019」奇怪装置相关的知识,希望对你有一定的参考价值。

#3144. 「APIO 2019」奇怪装置

题目描述

考古学家发现古代文明留下了一种奇怪的装置。该装置包含两个屏幕,分别显示两个整数 \(x\)\(y\)

经过研究,科学家对该装置得出了一个结论:该装置是一个特殊的时钟,它从过去的某个时间点开始测量经过的时刻数 \(t\),但该装置的创造者却将 \(t\) 用奇怪的方式显示出来。若从该装置开始测量到现在所经过的时刻数为 \(t\),装置会显示两个整数:\(x = ((t + \lfloor \fractB \rfloor) \bmod A)\),与 \(y = (t \bmod B)\)。这里 \(\lfloor x\rfloor\) 是下取整函数,表示小于或等于 \(x\) 的最大整数。

考古学家通过进一步研究还发现,该装置的屏幕无法一直工作。实际上,该装置的屏幕只在 \(n\) 个连续的时间区间段中能正常工作。第 \(i\) 个时间段从时刻 \(l_i\) 到时刻 \(r_i\)。现在科学家想要知道有多少个不同的数对 \((x, y)\) 能够在该装置工作时被显示出来。

两个数对 \((x_1, y_1)\)\((x_2, y_2)\) 不同当且仅当 \(x_1 \not = x_2\)\(y_1 \not = y_2\)

输入格式

第一行包含三个整数 \(n, A\)\(B\)

接下来 \(n\) 行每行两个整数 \(l_i, r_i\),表示装置可以工作的第 \(i\) 个时间区间。

输出格式

输出一行一个整数表示问题的答案。

数据范围与提示

对于全部数据,\(1\le n\le 10^6,1\le A,B\le 10^18,0\le l_i\le r_i\le 10^18,r_i<l_i+1\)


首先这玩意肯定是有环的。找到过后将所有线段平移到环内就可以直接做线段覆盖。

对于一个数\(t\),首先跟他同构的数可以表示为\(t+k*B\),因为要保证\(y\)相同。然后\(t\)每增加\(B\)\(x\)就增加\(B+1\),增加了\(\fracA\gcd(A,B+1)\)后有会同构。所以环大小\(\fracB*A\gcd(A,B+1)\)

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 1000005

using namespace std;
inline ll Get() ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') if(ch=='-') f=-1;ch=getchar();while('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0';ch=getchar();return x*f;

int n;
ll A,B,len;
struct node 
    ll l,r;
    bool operator <(const node &a)const 
        if(l!=a.l) return l<a.l;
        return r<a.r;
    
s[N<<1];
ll gcd(ll a,ll b) return !b?a:gcd(b,a%b);

int main() 
    n=Get(),A=Get(),B=Get();
    for(int i=1;i<=n;i++) s[i].l=Get(),s[i].r=Get();
    ll g=gcd(A,B+1);
    ll ans=0;
    if((long double)A/g*B>1e18) 
        for(int i=1;i<=n;i++) ans+=s[i].r-s[i].l+1;
     else 
        ll len=A/g*B;
        int tot=n;
        for(int i=1;i<=n;i++) 
            if(s[i].r-s[i].l+1>=len) 
                cout<<len;
                return 0;
            
            s[i].l%=len,s[i].r%=len;
            if(s[i].l>s[i].r) 
                s[++tot].l=0,s[tot].r=s[i].r;
                s[i].r=len-1;
            
        
        sort(s+1,s+1+tot);
        ll last=-1;
        for(int i=1;i<=tot;i++) 
            if(s[i].r<last) continue ;
            ans+=s[i].r-max(s[i].l-1,last);
            last=s[i].r;
        
    
    cout<<ans;
    
    return 0;

以上是关于#3144. 「APIO 2019」奇怪装置的主要内容,如果未能解决你的问题,请参考以下文章

[APIO2019T1]奇怪装置

APIO2019 题解

APIO 2016

[APIO2009]抢掠计划

p3627[APIO2009] 抢掠计划

洛谷P3625 - [APIO2009]采油区域