• sss


    <更新提示>

    <第一次更新>


    <正文>

    取模与异或

    Description

    ((n mod 1)oplus (n mod 2)oplus cdots oplus (n mod n))

    (nleq 10^{11})

    Input Format

    一行,一个正整数n。

    Output Format

    一行,一个正整数表示答案

    Sample Input

    5
    

    Sample Output

    2
    

    解析

    很容易想到『约数之和 整除分块』这道题。

    但是好像还不能直接整除分块做,应该我们不能快速求等差数列异或和之类的东西。于是考虑到异或是不进位加法,那就拆位试试看。

    也就是把式子转换成这个样子:

    [igoplus_{i=1}^nn mod i=sum_{k}sum_{i=1}^nleft(left lfloor frac{n mod i}{2^k} ight floor mod 2 ight) imes 2^k ]

    于是就可以推式子了

    [sum_{k}sum_{i=1}^nleft(left lfloor frac{n mod i}{2^k} ight floor mod 2 ight) imes 2^k\ \=sum_{i=1}^nsum_{k}left(left lfloor frac{n mod i}{2^k} ight floor mod 2 ight) imes 2^k\ \=sum_{i=1}^nsum_{k}left(left lfloor frac{n-lfloorfrac{n}{i} floor imes i }{2^k} ight floor mod 2 ight) imes 2^k ]

    (k)代表二进制中的每一位,是不是有点像类欧几里得算法求的那个式子,这引导我们继续推导下去。

    首先,枚举(k)(log_2n)级别的复杂度,我们能够承受,但是枚举(n)的复杂度是承受不了的,我们需要整除分块一下才能把枚举(n)的复杂度降下来。

    那么我们分块枚举(n),并枚举每一个(k),剩下的就是要快速求这个式子:

    [sum_{i=l}^{r}left lfloor frac{n-lfloorfrac{n}{i} floor imes i }{2^k} ight floor ]

    由于(k,lfloor frac{n}{i} floor)已经枚举了,我们就把有关量给换成常数(a,c)

    [sum_{i=l}^{r}left lfloor frac{n-lfloorfrac{n}{i} floor imes i }{2^k} ight floor=sum_{i=l}^rleftlfloor frac{n-a imes i}{c} ight floor ]

    已经很像类欧几里得的式子了,但仍然不能快速求,还要再处理一下下标,化简一下:

    [sum_{i=l}^rleftlfloor frac{n-a imes i}{c} ight floor=sum_{i=0}^{r-l}leftlfloor frac{n-a imes (i+l)}{c} ight floor ]

    (iin[0,r-l])时,((i+l))((r-i))取到的值域是一样的,那么我们就换一下:

    [sum_{i=0}^{r-l}leftlfloor frac{n-a imes (i+l)}{c} ight floor=sum_{i=0}^{r-l}leftlfloor frac{n-a imes (r-i)}{c} ight floor\=sum_{i=0}^{r-l}leftlfloor frac{n-a imes r+a imes i}{c} ight floor\=sum_{i=0}^{r-l}leftlfloor frac{a imes i+n-a imes r}{c} ight floor ]

    还记得(a=lfloor frac{n}{i} floor)吗?把它带回去。

    [sum_{i=0}^{r-l}leftlfloor frac{a imes i+n-a imes r}{c} ight floor\=sum_{i=0}^{r-l}leftlfloor frac{a imes i+n-lfloor frac{n}{i} floor imes r}{c} ight floor\=sum_{i=0}^{r-l}leftlfloor frac{a imes i+n mod r}{c} ight floor ]

    设$$f(a,b,c,n)=sum_{i=0}^nleftlfloorfrac{a imes i+b}{c} ight floor$$

    那么$$sum_{i=0}^{r-l}leftlfloor frac{a imes i+n mod r}{c} ight floor=f(a,n mod r,c,r-l)=f(leftlfloor frac{n}{i} ight floor,n mod r,2^k,r-l)$$

    枚举(l,r,k),直接用类欧几里得算法计算即可。

    这样做时间复杂度是(O(sqrt nlog^2n))的,可以直接暴力计算前(3 imes 10^7)个值,减小常数。

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    inline bool f(long long a,long long b,long long c,long long n)
    {
        if ( a == 0 ) return ( ( n + 1 ) & ( b / c ) & 1 ) > 0;
        if ( a >= c || b >= c )
        {
            long long val = ( n & 1 ) ? ( n + 1 ) / 2 * n : n / 2 * ( n + 1 );
            return ( ( f( a % c , b % c , c , n ) + ( a / c ) * val + ( n + 1 ) * ( b / c ) ) & 1 ) > 0;
        }
        else
        {
            long long val = ( a * n + b ) / c;
            return ( ( ( val * n ) ^ f( c , c - b - 1 , a , val - 1 ) ) & 1 ) > 0;
        }
    }
    int main(void)
    {
        freopen("mod.in","r",stdin);
        freopen("mod.out","w",stdout);
        long long ans = 0 , n;
        scanf("%lld",&n);
        long long T = min( n , 30000000LL );
        for (int i=1;i<=T;i++)
            ans ^= n % i;
        for (long long l=T+1,r;l<=n;l=r+1)
        {
            r = n/l ? min( n/(n/l) , n ) : n;
            long long lim = n/l * (r-l) + n%r , val = 0;
            for (long long k=1;k<=lim;k<<=1)
                val += f( n/l , n%r , k , r-l ) * k;
            ans ^= val;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
    

    <后记>

  • 相关阅读:
    RabbitMQ安装
    windows下安装Erlang
    利用StopWatch类监控Java代码执行时间并分析性能
    HttpClinet工具类
    Javap与JVM指令
    idea全局护眼色绿豆沙
    删除注册在Eureka的服务(无效,多余)
    Steam之两个list间交集、并集、差集
    微服务与SpringCloud简介
    VS code 豆沙绿护眼主题
  • 原文地址:https://www.cnblogs.com/Parsnip/p/11396562.html
Copyright © 2020-2023  润新知