• 3944: Sum[杜教筛]


    3944: Sum

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 3471  Solved: 946
    [Submit][Status][Discuss]

    Description

     

    Input

    一共T+1行
    第1行为数据组数T(T<=10)
    第2~T+1行每行一个非负整数N,代表一组询问
     

    Output

    一共T行,每行两个用空格分隔的数ans1,ans2
     

    Sample Input

    6
    1
    2
    8
    13
    30
    2333

    Sample Output

    1 1
    2 0
    22 -2
    58 -3
    278 -3
    1655470 2

    HINT

     

    Source

    我们考虑令:
    [F_n = sum_{d|n}varphi(d)]

    那么,有:
    [sum_{i=1}^{n}F_i = sum_{i=1}^{n}sum_{d|i}varphi(d) = sum_{d=1}^{n}varphi(d) imes lfloorfrac{n}{d} floor = sum_{d=1}^{n}sum_{i=1}^{lfloorfrac{n}{d} floor}varphi(i)]

    为什么最后一步可以这么转化呢?我们考虑一个 (i) ,论 (varphi(i)) 对答案的贡献:

    在最后一个等式的左边,(varphi(i)) 对答案的贡献为:(lfloorfrac{n}{i} floor),这很显然。

    在等式的右边,当 (i imes d le n) 的时候,(varphi(i))才会对答案产生贡献,所以对于每一个 (dlelfloorfrac{n}{i} floor)(varphi(i))都会对答案产生贡献,所以在等式右边,(varphi(i)) 对答案的贡献也为:(lfloorfrac{n}{i} floor)

    于是等式是成立的。

    不懂的话,移步这里:莫比乌斯反演与杜教筛 笔记

    那么就有:
    [sum_{i=1}^{n}varphi(i) = sum_{i=1}^{n}sum_{d|i}varphi(d) - sum_{d=2}^{n}sum_{i=1}^{lfloorfrac{n}{d} floor}varphi(i)]

    还有:
    [sum_{i=1}^{n}sum_{d|i}varphi(d) = sum_{i=1}^{n}i = frac{n imes(n+1)}{2}]

    所以:
    [sum_{i=1}^{n}varphi(i) = frac{n imes(n+1)}{2} - sum_{d=2}^{n}sum_{i=1}^{lfloorfrac{n}{d} floor}varphi(i)]

    所以算(sum_{i=1}^{n}varphi(i))的时候就可以记忆化搜索啦。

    据说,我们把 (N^{frac{2}{3}}) 之内的答案先筛出来,然后再进行记忆化搜索,复杂度就是 (O(N^{frac{2}{3}}))的了。

    然后同理,有:
    [sum_{i=1}^{n}mu(i) = 1 - sum_{d=2}^{n}sum_{i=1}^{lfloorfrac{n}{d} floor}mu(i)]

    时空复杂度均为 (O(N^{frac{2}{3}}))

    #include<cstdio>
    #include<cstring>
    #define clr(s) memset(s,0,sizeof s)
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,M=2e6+5;
    int T,n,m,tot,prime[M/3];bool check[M];
    ll phi[M],mu[M];
    ll alpha[N],beta[N];bool vis[N];
    inline void sieve(){
        m=M-5;mu[1]=phi[1]=1;
        for(int i=2;i<=m;i++){
            if(!check[i]) prime[++tot]=i,mu[i]=-1,phi[i]=i-1;
            for(int j=1;j<=tot&&i*prime[j]<=m;j++){
                check[i*prime[j]]=1;
                if(!(i%prime[j])){mu[i*prime[j]]=0;phi[i*prime[j]]=phi[i]*prime[j];break;}
                mu[i*prime[j]]=-mu[i];phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
        for(int i=1;i<=m;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
    }
    inline ll GetPhi(int x){
        return x<=m?phi[x]:alpha[n/x];
    }
    inline ll GetMu(int x){
        return x<=m?mu[x]:beta[n/x];
    }
    void solve(int x){
        if(x<=m) return ;
        int t=n/x;
        if(vis[t]) return ;
        vis[t]=1;
        alpha[t]=(ll)x*((ll)x+1)>>1;
        beta[t]=1;
        for(ll i=2,pos;i<=x;i=pos+1){//假如 x=2^31-1,那么i会爆int 
            pos=x/(x/i);
            solve(x/i);
            alpha[t]-=GetPhi(x/i)*(pos-i+1);
            beta[t]-=GetMu(x/i)*(pos-i+1);
        }
    }
    int main(){
        sieve();
        for(scanf("%d",&T);T--;clr(vis)){
            scanf("%d",&n);
            if(n<=m){
                printf("%lld %lld
    ",phi[n],mu[n]);
            }
            else{
                solve(n);
                printf("%lld %lld
    ",alpha[1],beta[1]);
            }
        }
        return 0;
    }
  • 相关阅读:
    宁泽涛世锦赛夺冠
    iOS手势识别的详细使用(拖动,缩放,旋转,点击,手势依赖,自定义手势)
    在xcode里面如何利用instrument
    Xcode 中搜索任何条件文本
    十大算法
    Object c中的alloc和init问题
    My97DaePicker 用js实现文本框日期相减求天数
    js 取消listbox选中的项
    C# OR/Mapping 数据处理模式学习
    ASP.NET实现列表页连接查询 拼接sql语句 绑定grivdView
  • 原文地址:https://www.cnblogs.com/shenben/p/6854363.html
Copyright © 2020-2023  润新知