首页 > 其他分享 >数学专题

数学专题

时间:2023-01-30 03:11:06浏览次数:45  
标签:专题 frac gcd 分块 int long 数学 ans

发现自己数学太菜了,所以练练!(


CF1780E Josuke and Complete Graph


链接:https://codeforces.com/contest/1780/problem/E

考虑$gcd$本质上是个啥。

假设我们现在知道某个数$d$,那么两个数$a$和$b$的$gcd$是$d$的条件其实是:

$a = k_1 d$,$b =k_2 d$且$(k_1,k_2) = 1$

又因为$(x,x+1) = 1$,所以其实$k_1$和$k_2$最接近的时候是差$1$

那么,我们现在假设我们枚举出某个数$d$,考虑什么时候$d$才能作为最大公约数出现在$[L,R]$之间

设第一个出现在$[L,R]$之间的$d$的倍数是$k_1 d$,则只要$(k_1 + 1) d$也在$[L,R]$内,$d$就能作为答案。

$k_1 = [\frac{L}{d}]$,$[ ]$表示上取整

有$(k_1 + 1) d <= R$

$d<=\frac{R}{k_1 + 1}$

显然,$k_1$是可以整除分块的。分块的过程中,$ [\frac{L}{d}] = k_1$时,范围为$[l,r]$

把两个$d$的范围取个交集,就是我们可以成为答案的$d$

在上整除分块中,$1$要单独处理一下。

#include <bits/stdc++.h>
using namespace std;
int main(){
    int T;
    cin>>T;
    while (T--){
        long long L,R;
        cin>>L>>R;
        long long ans = 0;
        ans = max(0ll,R/2-L+1);
        for (long long l=1,r;l<=L;l=r+1){
            long long t = ceil(double(L)/double(l));
            if (t == 1) break; 
            r = (L-1)/(t-1);
            ans += max(0ll,min(r,R/(t+1)) - l + 1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

标签:专题,frac,gcd,分块,int,long,数学,ans
From: https://www.cnblogs.com/si--nian/p/17074208.html

相关文章