zoukankan      html  css  js  c++  java
  • #3144. 「APIO 2019」奇怪装置

    #3144. 「APIO 2019」奇怪装置

    题目描述

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

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

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

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

    输入格式

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

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

    输出格式

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

    数据范围与提示

    对于全部数据,(1le nle 10^6,1le A,Ble 10^{18},0le l_ile r_ile 10^{18},r_i<l_{i+1})


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

    对于一个数(t),首先跟他同构的数可以表示为(t+k*B),因为要保证(y)相同。然后(t)每增加(B)(x)就增加(B+1),增加了(frac{A}{gcd(A,B+1)})后有会同构。所以环大小(frac{B*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;
    }
    
    
  • 相关阅读:
    为什么我的datagridview中显示的日期总把时间也显示出来了,请问怎样才能让它不显示呢?
    .net加载到vb 进程
    <转>RowState 介绍
    sqlserver 一个排序问题
    sqlserver 中含有某字符串
    网站链接的几种方式
    SQL Server 用SQL语句查找某个表的触发器
    获取文件名后缀
    mysql 排重查询
    while循环中不支持循环使用curl
  • 原文地址:https://www.cnblogs.com/hchhch233/p/11096863.html
Copyright © 2011-2022 走看看