• 牛客寒假训练营第二场D-整除分块


    牛客寒假训练营第二场D题

    Description:

    整除分块,又称数论分块。是数论算法中的重要技巧,你可以在各种需要枚举因子的连续求和类问题中见到它的身影。如杜教筛,莫比乌斯反演化简后的整除分段求和等。balabala
    ...(复制过来乱码,遂放弃),题目链接:https://ac.nowcoder.com/acm/contest/9982/D

    题意就是(S = {lfloor dfrac{N}{i} floor}),其中(iin[1, N]),输入T,N,x。T表示测试的个数,求每个测试(lfloor dfrac{N}{x} floor)去重集合S中降序排序第几大。

    示例输入

    2 // 测试的个数
    25 9
    1000000000 1000000000
    

    示例输出

    8
    63244
    

    说明

    当n=25时候,(S={25,12,8,6,5,4,3,2,1}) (lfloor dfrac{25}{9} floor=2),2在S集合中是降序排列的第8个,所以输出8

    Solution:

    1、首先了解一下整除分块的性质,对于一个正整数N

    1、(lfloor dfrac{N}{i} floor)最多有(2sqrt{N})

    证明:

    • (i le sqrt{N}), 一共有(sqrt{N})
    • (i > sqrt{N})(dfrac{N}{i} <= sqrt{N}), 最多有(sqrt{N})种;因为有可能对于所有的(i > sqrt{n})(dfrac{N}{i} < sqrt{N}),那么此时只有(sqrt{N} - 1)

    根据这个题目别人的代码我可以知道:当(lfloor sqrt{N} floor = lfloor dfrac{N}{sqrt{N}} floor)时,有(2sqrt{N} - 1)种(不知道如何证明暂时

    2、(b = lfloor dfrac{N}{a} floor) 时, (a = lfloor dfrac{N}{b} floor)

    这个类似于实数除法中除数和商的互逆性质:$b = dfrac{N}{a} $ 时, (a = dfrac{N}{b})

    不知如何证明

    3、对于(lfloor dfrac{N}{j} floor)(lfloor dfrac{N}{i} floor)相等时,j最大的取值是(lfloor dfrac{N}{lfloor dfrac{N}{i} floor} floor)

    也就是说(forall j in [i, lfloor dfrac{N}{lfloor dfrac{N}{i} floor} floor])(lfloor dfrac{N}{j} floor = lfloor dfrac{N}{i} floor)

    证明看这个哥哥的:https://www.cnblogs.com/0xfffe/p/9648943.html

    2、本题解法

    #include<bits/stdc++.h>
    using namespace std;
    int T, N, x;
    int main()
    {
    	scanf("%d", &T);
    	while(T--){
    		scanf("%d %d", &N, &x);
    		int sq = sqrt(N);
    		int tmp = N/x;
            int tot;
            // 求出S中集合元素个数(即有多少种数字)
            if(sq==N/sq) tot = 2*sq-1;
            else		 tot = 2*sq;
            
            // 如果 x >= sqrt(n)
    		if(x>=sq) printf("%d
    ",tot-tmp+1);
            // else
    		else printf("%d
    ",x); // N/x < sqrt(n)
    	}
    	return 0;
    }
    
    

    这里主要用到了性质1和2,

    比如对于N=25,(S={25,12,8,6,5,4,3,2,1})

    • x = 2时,25/2 = 12,ans = 2;也就是说ans = x,这是因为x 和 anx/x 在S中是关于(sqrt{N})对称的
    • x = 10时,25/10 = 2, ans = |S| - 2+1 = 8; 即ans = |S| - N/x + 1

    对于另一个类似的题目,主要用到性质3

    (sum_{i=1}^{N} lfloor dfrac{N}{i} floor)

    // 求和模板
    #define long long ll
    void summ(ll  N)
    {
    	ll ans;
    	for(ll l=1, r; l<=n; l=r+1){
    		r = n/(n/i); // 区间右端点 
    		ans += (r-l+1)*(n/i); // [l,r]区间内部的都是n/i 
    	}
    	return ans;
     } 
    

    参考

    https://www.limstash.com/articles/201901/1206

    https://www.cnblogs.com/hunxuewangzi/p/14373198.html

    https://www.cnblogs.com/0xfffe/p/9648943.html

  • 相关阅读:
    CodeForces-455A Boredom
    UVA-12627 Erratic Expansion
    汉诺塔系列问题
    CodeForces-999D Equalize the Remainders
    CodeForces-1061D TV Shows
    CodeForces-1061B Views Matter
    UVALive-7261 Xiongnu's Land
    HDU-4990 Reading comprehension
    -------------------------------用MyBatis处理表与表之间的关联关系----------------------------------
    -------------计算机里面算法-----------
  • 原文地址:https://www.cnblogs.com/VanHa0101/p/14374915.html
Copyright © 2020-2023  润新知