zoukankan      html  css  js  c++  java
  • 数论::整除分块

    题目链接:洛谷P3935

    题目描述:

    ,求

    输入格式

    输入共一行,两个数,l,,r。

    输出格式

    输出共一行,一个数,为f(i),i∈(l,n)对998244353取模的结果。

    分析:实际上,我们有

     反演d(i),我们有d(i)等价于

    不妨先设函数f(x)为该式的朴素情况

    即ans等价于

     即ans=f(r/i)-f((l-1)/j)

     对于f(x),不难看出一种O(n)的暴力算法,但是显然我们需要sqrt(n)的

    我们可以先枚举观察r=10的情况,观察r/i的值

    1   2  3  4  5  6  7  8  9  10
    10 5  3  2  2  1  1  1  1  1

    不难发现也不难证明,相同的数都是连续的,可以把它分成一块一块值相同的段。那么我们可以利用这个性质,对于每一块,将这个块的数字乘上块的长度,就可以求解这一块的和了。

    首先是块的数量,在i在1到根号r之间时,最多有根号r个块,在大于根号r时,r/i<=根号r,所以一共最多有2√n种分块

    当某一块的左端点为l,那么它的右端点r就是(r/(r/l))向下取整,至此,f(x)的求法为

    ll ans=0;
    for(ll l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans+=(r-l+1)*(n/l);
    }

    所以Ans也可轻松解出

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        long long left,right;
        scanf("%lld%lld",&left,&right);
        long long sum1=0,sum2=0;
        for(long long l=1,r;l<=right;l=r+1)
        {
            r=right/(right/l);
            sum1=(sum1+(right/l)%998244353*((r-l+1)%998244353)%998244353)%998244353;
        }
        for(long long l=1,r;l<=left-1;l=r+1)
        {
            r=(left-1)/((left-1)/l);
            sum2=(sum2+((left-1)/l)%998244353*((r-l+1)%998244353)%998244353)%998244353;
        }
        printf("%lld
    ",((sum1-sum2)%998244353+998244353)%998244353);
        return 0;
    }



  • 相关阅读:
    【BZOJ 2565】 最长双回文串
    【BZOJ 2160】 拉拉队排练
    【POI 2010】 Antisymmetry
    【HDU 3068】 最长回文
    【POJ 3974】 Palindrome
    【POJ 2503】 Babelfish
    【POJ 3349】 Snowflake Snow Snowflakes
    【BZOJ 2457】 双端队列
    根文件系统的构建与分析(一)之流程分析
    Linux MTD系统剖析
  • 原文地址:https://www.cnblogs.com/iloveysm/p/12398274.html
Copyright © 2011-2022 走看看