ZOJ The Sum of Unitary Totient (Min_25筛)

Posted azznaz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

 

以上是关于ZOJ The Sum of Unitary Totient (Min_25筛)的主要内容,如果未能解决你的问题,请参考以下文章

The sum of numbers form 0 to n.(20.9.2017)

1317. Convert Integer to the Sum of Two No-Zero Integers

LeetCode --- 1317. Convert Integer to the Sum of Two No-Zero Integers 解题报告

LeetCode --- 1317. Convert Integer to the Sum of Two No-Zero Integers 解题报告

ZOJ - 2110 Tempter of the Bone

check whether the subset(no need to be consective) and be sum of X