zoukankan      html  css  js  c++  java
  • [SDOi2012]longge的问题

    题意:

    Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。

    对于100%的数据,0<N<=2^32

    题解:

    (网上全部都是欧拉函数解法(甚至还有莫比乌斯反演??)

    像我这种蒟蒻就真的想不到了。

    我就用容斥解决了这道题。

    既然要考虑gcd,而且不能暴力,就肯定要把n质因数分解了。

    n=p1^q1 * p2^q2 *... * pk^qk

    gcd(a,b)的本质是:把a质因数分解,b质因数分解,对于每一个质因子,系数取min再相乘就是gcd

    所以考虑一下n的所有因数。(远远不到sqrt(N)个,网上有说ln(n)??)

    对于每一个因数p=p1^d1 * p2^d2 *... * pk^dk,它在n以内的倍数都有p,

    但是,假设d1<q1时,同样是 p1^(d1+1) * p2^d2 *... * pk^dk的倍数的数,gcd就不是p了。

    同理,每一个系数d如果能够加1,那么这个新因数的倍数们与n的gcd 就不是现在的p了。

    我们把p的每一位的系数d分别能加1就加1,构造一个新数M,M的倍数就是一些不由p贡献的数。

    把所有这些M的倍数减去,但是,最小公倍数们又减多了。再加上2个lcm,加上3个lcm们。。。。。。。

    这就是容斥啦。

    因为,2^32以内的一个数的不同质因子,最多只有10个(2*3*5*7*11*13*17*19*23*29 > 2^32)

    所以,每次就2^10容斥一下,一定不会tle~!!!!!!!!!!!!!!

    就这样,两个dfs。一个枚举因数,一个用这个因数容斥。

    复杂度上限:O(因数个数*(2^10))

    比网上一般的欧拉函数做法 O(因数个数* sqrt(n))的做法要快。

    (2018.8.10补充:而且,对于gcd(n,1~m)的和,其中m远远大于n,也可以这样做!!!网上的方法就不行了。)

    (upda:2019.3.22:之前太辣鸡了,反演是容斥的超集)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n;
    ll has[20],cnt;
    ll ans;
    struct node{
        ll num,mi;
    }c[20];
    ll tot;//sum of primes
    ll sum=0;
    void sol(){
        ll k=n;
        for(ll i=2;i*i<=n;i++){
            if(k%i==0){
                c[++tot].num=i;
                while(k%i==0) c[tot].mi++,k/=i;
            }
        }
        if(k!=1) c[++tot].num=k,c[tot].mi++;
    }
    void dfs1(int x,int cnt,ll digi){
        if(x==tot+1){
            if(cnt&1) sum-=n/digi;
            else sum+=n/digi;
            return;
        }
        dfs1(x+1,cnt,digi);
        if(has[x]<c[x].mi) dfs1(x+1,cnt+1,digi*c[x].num);
    }
    void dfs2(int x,ll now){
        if(x==tot+1){
            sum=0;
            dfs1(1,0,now);
            ans+=sum*now;
            return;
        }
        ll to=1;
        for(int i=0;i<=c[x].mi;i++){
            has[x]=i;
            dfs2(x+1,now*to);
            to*=c[x].num;
        }
    }
    int main()
    {
        scanf("%lld",&n);
        sol();
        dfs2(1,1);
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    由PhysicalFileProvider构建的物理文件系统
    Net Core WebApi单元测试
    多个项目使用NET Core
    ReactNative
    定制样式插入到ueditor
    ES6的Class
    Redis存储Session
    二叉 查找树 排序树 搜索树
    SignalR实现实时日志监控
    KNN(k-nearest neighbor的缩写)又叫最近邻算法
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9371942.html
Copyright © 2011-2022 走看看