zoukankan      html  css  js  c++  java
  • 【LG5171】Earthquake

    【LG5171Earthquake】

    题面

    洛谷

    题解

    本题需要用到类欧几里得算法。

    前置知识:类欧几里得

    就是求函数$$varphi (a,b,c,n)=sum_{i=0}^n leftlfloorfrac {ai+b}c ight floor$$
    的值(其实还有两种形式,但是我还不会这里不做介绍)。

    它的几何意义是直线(y=frac {ax+b}c)([0,n])下方或过直线的第一象限内的整点数

    (xi(i)=lfloorfrac {ai+b}c floor)

    由结论(lfloorfrac{Ax}y floor = lfloorfrac{A(x;mod;y)}y floor + Alfloorfrac xy floor)

    可以得到

    [egin{aligned} xi(i)&=leftlfloorfrac{ai}c+frac bc ight floor \&=leftlfloorfrac{(amod c)i+(bmod c)} c ight floor+iBiglfloorfrac acBig floor+Biglfloorfrac bcBig floor end{aligned} ]

    然后可以得到(varphi(a,b,c,n)=varphi(amod c,bmod c, c, n)+frac {n(n+1)}2lfloorfrac ac floor+(n+1)lfloorfrac bc floor)

    现在我们将(xi(i))的值限制在了([0,n])之内,考虑将(varphi)用新的式子表示出来:

    [egin{aligned} varphi(a,b,c,n)&=sum_{i=0}^nsum_{d=1}^{lfloorfrac {an+b}c floor}left[lfloorfrac {ai+b}c floorgeq d ight]\&=sum_{i=0}^nsum_{d=0}^{lfloorfrac {an+b}c floor-1}left[a^{-1}clfloorfrac {ai+b}c floorgeq a^{-1}c(d+1)>a^{-1}(cd+c-1) ight]\&=sum_{i=0}^nsum_{d=0}^{lfloorfrac {an+b}c floor-1}left[i>frac {cd+c-b-1}{a} ight] end{aligned} ]

    而右边艾弗森括号里的相当于统计有多少个数大于(frac {cd+c-b-1}{a}),就相当于(n-lfloorfrac {cd+c-b-1}{a} floor),那么

    [egin{aligned} varphi(a,b,c,n)&=sum_{d=0}^{lfloorfrac {an+b}c floor-1}(n-leftlfloorfrac {cd+c-b-1}{a} ight floor)\ &=nleftlfloorfrac {an+b}c ight floor-sum_{d=0}^{lfloorfrac {an+b}c floor-1}leftlfloorfrac {cd+c-b-1}{a} ight floor\ &=nleftlfloorfrac {an+b}c ight floor-varphi(c,c-b-1,a,leftlfloorfrac {an+b}c ight floor-1)\ &=nleftlfloorfrac {an+b}c ight floor-varphi(c,c-b-1,a,xi(n)-1) end{aligned} ]

    现在就可以递归处理了,至于复杂度,仔细思考一下发现和(gcd)复杂度一样,为(O(log n))

    代码实现:

    long long f(long long a, long long b, long long c, long long n) { 
    	if (!a) return b / c * (n + 1); 
    	else if (a >= c || b >= c) return f(a % c, b % c, c, n) + n * (n + 1) / 2 * (a / c) + (n + 1) * (b / c); 
    	else {
    		long long m = (a * n + b) / c; 
    		return n * m - f(c, c - b - 1, a, m - 1); 
    	} 
    } 
    

    关于此题

    [ax+by-cleq 0 ]

    就是求(y=frac {c-ax}{b})下方或过直线在第一象限及正半轴上的整点数。

    (n=lfloorfrac ca floor),那么两端的点就为((0,frac cb),(n,frac {c-an}b))

    显然可以把两端的(y)值调换一下,那么两点变为((0,frac {c-an}b),(n,frac cb))

    此时这条直线变为(y=frac ab x+frac {c-an}{b}=frac {ax+(c;mod;a)}b),然后套到类欧的模板里再加上坐标轴上的贡献即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    using namespace std; 
    long long a, b, c; 
    long long f(long long a, long long b, long long c, long long n) { 
    	if (!a) return b / c * (n + 1); 
    	else if (a >= c || b >= c) return f(a % c, b % c, c, n) + n * (n + 1) / 2 * (a / c) + (n + 1) * (b / c); 
    	else {
    		long long m = (a * n + b) / c; 
    		return n * m - f(c, c - b - 1, a, m - 1); 
    	} 
    } 
    int main () { 
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin); 
    #endif 
    	cin >> a >> b >> c; 
    	printf("%lld
    ", f(a, c % a, b, c / a) + c / a + 1); 
        return 0; 
    } 
    
  • 相关阅读:
    关于拷贝构造函数和赋值运算符
    笔试题(转)
    Pro *C/C++学习笔记(一)
    __cdecl
    Visual Studio 2010中C++的四大变化(转)
    小小递归函数的执行过程
    stl string常用函数
    【C/C++ string】之strcpy函数
    409 Excuses, Excuses!
    10878 Decode the tape
  • 原文地址:https://www.cnblogs.com/heyujun/p/11804358.html
Copyright © 2011-2022 走看看