其他分享
首页 > 其他分享> > ZOJ The Sum of Unitary Totient (Min_25筛)

ZOJ The Sum of Unitary Totient (Min_25筛)

作者:互联网

题意: 给你一个函数f(n)=(p1a1-1)(p2a2-1)...(prar-1) ,n=p1a1p2a2...pra 求\[\sum\limits_{i = 1}^n {f(i)} \],\[n <  = 1e9\]

思路: \[f(p) = p - 1,f({p^k}) = {p^k} - 1\],直接用min_25筛就可以了,按道理来讲我感觉min_25筛是稳过的,但我交了几十次才过,要不是在网上看到有人用min_25筛过了我还以为我想错了

#include<bits/stdc++.h>
#define ms(x) memset(x,0,sizeof(x))
#define sws ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int maxn=8e4+5;
const ll mod=1e9+7;
int id1[maxn],id2[maxn];
int w[maxn];
int vis[maxn];
int prime[maxn];
ll sup[maxn];
int tot;
int sqr;
int cnt;
ll g[maxn];
int h[maxn];
ll n;
int k;
inline ll S(int x,int y){
       if(x<=1||prime[y] > x) return 0;
       k=x<=sqr?id1[x]:id2[n/x];
       register ll ans=1ll*(g[k]-h[k]-(sup[y-1]-y+1));
       for(register int i=y;i<=tot&&1ll*prime[i]*prime[i]<=x;++i){
               register ll pk1=1ll*prime[i],pk2=pk1*prime[i];
               for(;pk2<=x;pk1=pk2,pk2=pk2*prime[i]){
                     ans+=(pk1-1)*S(x/pk1,i+1)+pk2-1;
               }
       }
       return ans;
}
int upper;
int main(){

    tot=0;
    register int i,j;
    for( i=2;i<maxn;++i){
        if(!vis[i]){
            prime[++tot]=i;
            sup[tot]=sup[tot-1]+i;
        }
        for(j=1;j<=tot&&i*prime[j]<maxn;++j){
            vis[i*prime[j]]=1;
                if(i%prime[j]==0){
                break;
            }
        }
    }
    while(~scanf("%lld",&n)){
            cnt=0;
    upper=n;
    sqr=sqrt(upper);
    for(i=1;i<=upper;i=j+1){
        j=upper/(upper/i);
        w[++cnt]=upper/i;
        if(w[cnt]<=sqr) id1[w[cnt]]=cnt;
        else id2[j]=cnt;
        g[cnt]=1ll*w[cnt]*(w[cnt]+1)/2-1;
        h[cnt]=w[cnt]-1;
    }
    register int x;
    for(j=1;j<=tot&&1ll*prime[j]*prime[j]<=upper;++j)if(h[j]!=h[j-1]||g[j]!=g[j-1]){
        for(i=1;i<=cnt&&1ll*prime[j]*prime[j]<=w[i];++i){
             x=w[i]/prime[j];
             k=x<=sqr?id1[x]:id2[n/x];
            g[i]-=(prime[j])*(g[k]-(sup[j-1]));
            h[i]-=(h[k]-(j-1));
        }
    }
            printf("%lld\n",S(n,1)+1);
    }
    return 0;
}

 

标签:25,Unitary,const,Min,int,ll,min,maxn
来源: https://www.cnblogs.com/azznaz/p/11517872.html