51nod 1188

渊哥给我这题,我还以为是反演,然后还真推出来了

$$ans=\sum_{d=1}(\lfloor\frac{n}{i}\rfloor)^2\sum_{i|d}\mu(\frac{d}{i})i$$

然后51nod 跑了3sec T了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=5000006;

int prime[N],cnt;
bool he[N];
ll ji[N];

void chu()
{
    ji[1]=1;
    for(int i=2;i<N;++i)
    {
        if(!he[i])
        {
            prime[++cnt]=i;
            ji[i]=i-1;
        }
        for(int j=1;j<=cnt&&prime[j]*i<N;++j)
        {
            he[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                ji[i*prime[j]]=ji[i]*prime[j];
                break;
            }
            ji[i*prime[j]]=ji[i]*ji[prime[j]];
        }
    }
    
    for(int i=1;i<N;++i)
      ji[i]+=ji[i-1];
}

int T,n;

int main(){
    
    //freopen("in.in","r",stdin);
    
    chu();

    T=read();
    
    ll ans;
    int nx;
    
    while(T--)
    {
        n=read();
        
        ans=0;
        for(int i=1;i<=n;i=nx+1)
        {
            nx=n/(n/i);
            ans+=(ll)(n/i)*(n/i-1)*(ji[nx]-ji[i-1]);
        }
        printf("%lld\n",ans/2);
    }

}
反演

正解是

要求 gcd(n,i)==K 的数量,可以转化成求 gcd(n/K,i/K)==1 的个数

$$ans=\sum_{i=2}^n\sum_{j=1}^{i-1}gcd(i,j)$$

$$ans=\sum_{i=2}^n\sum_{j|i}^{i-1}\phi(\frac{i}{j})j$$

$$ans=\sum_{i=2}^n\sum_{j=1}^{i*j<=n}\phi(i)j$$

$O(nlog(n))$

正解也会T,51nod真玄学

#pragma GCC optimize("O3")
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=5000006;
const int TT=50006;

int prime[348600],cnt;
bool he[N];
int ou[N];
ll an[N];

void chu()
{
    ou[1]=1;
    for(int i=2;i<N;++i)
    {
        if(!he[i])
        {
            prime[++cnt]=i;
            ou[i]=i-1;
        }
        for(int j=1;j<=cnt&&prime[j]*i<N;++j)
        {
            he[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                ou[i*prime[j]]=ou[i]*prime[j];
                break;
            }
            ou[i*prime[j]]=ou[i]*ou[prime[j]];
        }
    }
    
    ll t1;
    for(int i=2;i<N;++i)
      for(int j=1;j*i<N;++j)
        an[i*j]+=ou[i]*j;
    for(int i=2;i<N;++i)
      an[i]+=an[i-1];
}

int T,n;

int main(){
    
    //freopen("in.in","r",stdin);
    //freopen("51nod_Problem_1188_Test_21_In.txt","r",stdin);
    //freopen("out.out","w",stdout);
    
    chu();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        printf("%lld\n",an[n]);
    }
}
正解

 

posted @ 2017-10-16 20:27  A_LEAF  阅读(149)  评论(0编辑  收藏  举报