ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

陕西省第九届大学生程序设计竞赛 C.GCD 整除分块

2022-06-19 21:34:42  阅读:200  来源: 互联网

标签:GCD 分块 ll v1 v2 倍数 整除


 

这题值得好好写写:

很快想到了如果一堆数的公因数都是a,那么必定都是a的倍数(废话)

那么如果在[l,r]里找到最小的a的倍数,再逐渐+a,+2*a,得到的一堆数必定gcd==a的条件

而且,这些数的个数还要至少为k

问题转化成了求a,a满足[l,r]里面是a的倍数的数大于等于k个

plan A:

写了个枚举,a的最大值是(r-l+1)/k;

当然狠狠地超时了

plan B:

看了题解后明白了一种叫差分的思想和一种叫整除分块的东西

差分思想:其实是 r/a-(l-1)/a>=k

没想到这个,我连分块都摸不到hhh(安慰自己想不到hin正常

观察r/a:

——by pengym 侵删

这里r就是n,a就是i。

说明r/a的值是有限的,且同一个r/a,可能对应了好几个a

那是不是,用整除分块可以把a切成一块块的,在每个块里面,r/a的值和(l-1)/a的值是固定的,只要check一下满不满足>=k这个条件,就可以直接计算这个块的贡献:

这个块的长度!

但是实现起来,emmm:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll l,r,k;
map<ll,ll>Hash;
int main()
{
    ll ans=0;
    cin>>l>>r>>k;
    l--;
    for(ll L=1,R;L<=r;L=R+1)
    {   
        R=r/(r/L);
        ll v1=r/L;
        ll v2=l/L;
        if(v2) R=min(R,l/v2);
        if(v1-v2>=k) ans+=(R-L)+1;
    }
    cout<<ans;
}

我们发现如果没有这部分,是会卡在89tps的:

 ll v1=r/L;
 ll v2=l/L;
 if(v2) R=min(R,l/v2);

把每次l/v2和r/v1的结果打出来,发现v1和v2的大小关系不确定

就是说我们有l,还有r,每个数都有自己的分块切法,显然不会完全相同

那当然是取右边界小的那个了!再多出去一些,可能对其中有个数来说,就跑到下一个块了

然后好奇了一下,这样改会不会对时间复杂度有影响?

答:没啥头绪,不会想,反正跑得挺快的hhh



标签:GCD,分块,ll,v1,v2,倍数,整除
来源: https://www.cnblogs.com/liyishui2003/p/16391470.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有